Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 1 729

/ вопрос открыт /

Приветствую, уважаемые эксперты!

В приложении прога, которая сворачивает окошко в трэй и по таймеру меняет иконку в этом трэйе.
Подскажите пжлста почему когда я ее сворачиваю, то в начальный момент она занимает в памяти около 500 Кб, а через какое-то время разрастается до 1Мб.
Заранее благодарю
Delphi7

Приложение:
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls, ComCtrls, ShellAPI, ExtCtrls;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. Label1: TLabel;
  12. Label2: TLabel;
  13. Label3: TLabel;
  14. Label4: TLabel;
  15. Timer1: TTimer;
  16. procedure FormCreate(Sender: TObject);
  17. procedure Timer1Timer(Sender: TObject);
  18. procedure FormClose(Sender: TObject; var Action: TCloseAction);
  19. private
  20. { Private declarations }
  21. FIconData:TNotifyIconData;
  22. FSecondIcon:boolean;
  23. protected
  24. procedure WndProc(Var Msg:TMessage); override;
  25. public
  26. { Public declarations }
  27. procedure CreateTrayIcon(n:Integer);
  28. procedure DeleteTrayIcon(n:Integer);
  29. procedure DoSomethingElse;
  30. procedure HideMainForm;
  31. procedure RestoreMainForm;
  32. end;
  33.  
  34. var
  35. Form1: TForm1;
  36.  
  37. implementation
  38.  
  39. {$R *.dfm}
  40.  
  41. procedure TForm1.FormCreate(Sender: TObject);
  42. var MyDate: TDateTime;
  43. begin
  44. MyDate:=39979;
  45. Label1.Caption:=DateToStr(MyDate);
  46. Label4.Caption:=IntToStr(round(MyDate-Date))+' äíåé';
  47. end;
  48. //
  49. procedure TForm1.DoSomethingElse;
  50. begin
  51. Sleep(2000)
  52. end;
  53. //
  54. procedure TForm1.HideMainForm;
  55. begin
  56. Application.ShowMainForm := False;
  57. ShowWindow(Application.Handle, SW_HIDE);
  58. ShowWindow(Application.MainForm.Handle, SW_HIDE);
  59. end;
  60. //
  61. procedure TForm1.RestoreMainForm;
  62. begin
  63. Application.ShowMainForm := True;
  64. ShowWindow(Application.Handle, SW_RESTORE);
  65. ShowWindow(Application.MainForm.Handle, SW_RESTORE);
  66. SetForegroundWindow(Application.MainForm.Handle);
  67. end;
  68. //
  69. procedure TForm1.WndProc(Var Msg:TMessage);
  70. begin
  71. inherited;
  72. if (Msg.wParam = SC_MINIMIZE)
  73. then
  74. begin
  75. HideMainForm;
  76. Timer1.Enabled:=true;
  77. CreateTrayIcon(100);
  78. end;
  79. //
  80. if (Msg.lParam = WM_RBUTTONDOWN)
  81. then
  82. begin
  83. FSecondIcon:= not FSecondIcon;
  84. if FSecondIcon
  85. then FIconData.hIcon:=LoadIcon(0,IDI_EXCLAMATION)
  86. else FIconData.hIcon:=Application.Icon.Handle;
  87. Shell_NotifyIcon(NIM_MODIFY,@FIconData)
  88. end;
  89. //
  90. if (Msg.lParam = WM_LBUTTONDOWN)
  91. then
  92. begin
  93. Timer1.Enabled:=false;
  94. RestoreMainForm;
  95. end;
  96. end;
  97. //
  98. procedure TForm1.CreateTrayIcon(n:Integer);
  99. begin
  100. with FIconData do
  101. begin
  102. cbSize:=SizeOf(FIconData);
  103. wnd:=Handle;
  104. uID:=n;
  105. uFlags:=NIF_MESSAGE or NIF_ICON or NIF_TIP;
  106. uCallbackMessage:=WM_USER+123;
  107. hIcon:=Application.Icon.Handle;
  108. StrPCopy(szTip,Label3.Caption+' '+Label4.Caption)
  109. end;
  110. DoSomethingElse;
  111. Shell_NotifyIcon(NIM_ADD,@FIconData)
  112. end;
  113. //
  114. procedure TForm1.DeleteTrayIcon(n:Integer);
  115. begin
  116. with FIconData do
  117. begin
  118. cbSize:=SizeOf(FIconData);
  119. wnd:=Handle;
  120. uID:=n;
  121. end;
  122. Shell_NotifyIcon(NIM_DELETE, @FIconData);
  123. end;
  124. //
  125. procedure TForm1.Timer1Timer(Sender: TObject);
  126. begin
  127. FSecondIcon:= not FSecondIcon;
  128. if FSecondIcon
  129. then FIconData.hIcon:=LoadIcon(0,IDI_EXCLAMATION)
  130. else FIconData.hIcon:=Application.Icon.Handle;
  131. Shell_NotifyIcon(NIM_MODIFY,@FIconData)
  132. end;
  133.  
  134. procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
  135. begin
  136. DeleteTrayIcon(100);
  137. Action:=caFree;
  138. end;
  139.  
  140. end.


Muratov Radik Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: Muratov Radik (статус: Посетитель)
Вопрос отправлен: 26 июня 2008, 09:16
Состояние вопроса: открыт, ответов: 1.

Ответ #1. Отвечает эксперт: Вадим К

Здравствуйте, Muratov Radik!
Я так понимаю, вы боитесь, что у вас утечки памяти? Но в таком случае возникает вопрос в том, как вы измерели эту "утечку". Если вы пользуетесь диспетчером задач, то могу сразу предупредить: освободив в программе 4 байта памяти не спешите сразу это увидеть в диспетчере задач. Скорее всего, там ничего не поменяется. Всё дело в том, что делфи вставляет свой менеджер-посредник для памяти. И когда выделяте 10 байт, он выделяет от 64кб до нескольких мегабайт. Потом может использовать зарезервированую память, что бы выделить для следующего запроса. Это происходит так, потому что процедура запроса памяти у ОС достаточно накладная и долгая. (на выделение 16 байт и 1 мегабайта уйдёт почти одно и то же время. правда не могу гарантировать, что ОС выдаст вам строго 16 байт).
Дефловский менеджер памяти особенно эффективен при частых мелких (десятки - сотни байт) выделениях/освобождениях памяти и обгонят в таком случае непосредственное выделение в несколько раз.
Это первая причина, почему не стоит доверять диспетчеру задач и другим подобным утилитам.
Вторая причина странного поведения заключается в том, что когда вы сворачиваете приложение, происходит перераспределение памяти - обычное поведение виндовс. Свернув/развернув приложение, которое уже достаточно долго проработало, можно заметить существенные изменения использованной памяти (вот сейчас я пишу в Опере. диспетчер показывает занято 88М. свернул - 8. развернул - 40). В диспетчере задач можно включить колонку Виртуальная память - вот ей с большим трудом можно доверять. И то, не всегда.

Просмотрев код, я ненашёл ничего особо противозаконного. Если хотите убедиться в том, что утечек нет, оставте программу запущенной на несколько дней-недель. Если утечка есть, то это будет заметно.Есть другой способ - использовать альтернативный менеджер памяти. Он и покажет утечки, если они есть. Я рекомендую FastMM4 (Скачать). Если не разберётсь, как использовать - пишите, разберёмся. Для начала можно почитать вот это.
И если Fastmm укажет на утечку, вот тогда пишите, что именно он выдаёт, будет разбирать. Хотя замечу, что иногда он ошибается даже на самом простом коде.

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 26 июня 2008, 23:47
Оценка за ответ: 5

Комментарий к оценке: Большое спасибо за развернутый ответ. Я действительно замерял по диспетчеру задач. Запускаю утром(492Кб), а после обеда уже 1.5Мб. Вот

Мини-форум вопроса

Мини-форум пуст.

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:30
Выполнено за 0.02 сек.