|
Вопрос # 1 729/ вопрос открыт / |
|
Приветствую, уважаемые эксперты!
В приложении прога, которая сворачивает окошко в трэй и по таймеру меняет иконку в этом трэйе.
Подскажите пжлста почему когда я ее сворачиваю, то в начальный момент она занимает в памяти около 500 Кб, а через какое-то время разрастается до 1Мб.
Заранее благодарю
Delphi7
Приложение: Переключить в обычный режим- unit Unit1;
-
- interface
-
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls, ComCtrls, ShellAPI, ExtCtrls;
-
- type
- TForm1 = class(TForm)
- Label1: TLabel;
- Label2: TLabel;
- Label3: TLabel;
- Label4: TLabel;
- Timer1: TTimer;
- procedure FormCreate(Sender: TObject);
- procedure Timer1Timer(Sender: TObject);
- procedure FormClose(Sender: TObject; var Action: TCloseAction);
- private
- { Private declarations }
- FIconData:TNotifyIconData;
- FSecondIcon:boolean;
- protected
- procedure WndProc(Var Msg:TMessage); override;
- public
- { Public declarations }
- procedure CreateTrayIcon(n:Integer);
- procedure DeleteTrayIcon(n:Integer);
- procedure DoSomethingElse;
- procedure HideMainForm;
- procedure RestoreMainForm;
- end;
-
- var
- Form1: TForm1;
-
- implementation
-
- {$R *.dfm}
-
- procedure TForm1.FormCreate(Sender: TObject);
- var MyDate: TDateTime;
- begin
- MyDate:=39979;
- Label1.Caption:=DateToStr(MyDate);
- Label4.Caption:=IntToStr(round(MyDate-Date))+' äíåé';
- end;
- //
- procedure TForm1.DoSomethingElse;
- begin
- Sleep(2000)
- end;
- //
- procedure TForm1.HideMainForm;
- begin
- Application.ShowMainForm := False;
- ShowWindow(Application.Handle, SW_HIDE);
- ShowWindow(Application.MainForm.Handle, SW_HIDE);
- end;
- //
- procedure TForm1.RestoreMainForm;
- begin
- Application.ShowMainForm := True;
- ShowWindow(Application.Handle, SW_RESTORE);
- ShowWindow(Application.MainForm.Handle, SW_RESTORE);
- SetForegroundWindow(Application.MainForm.Handle);
- end;
- //
- procedure TForm1.WndProc(Var Msg:TMessage);
- begin
- inherited;
- if (Msg.wParam = SC_MINIMIZE)
- then
- begin
- HideMainForm;
- Timer1.Enabled:=true;
- CreateTrayIcon(100);
- end;
- //
- if (Msg.lParam = WM_RBUTTONDOWN)
- then
- begin
- FSecondIcon:= not FSecondIcon;
- if FSecondIcon
- then FIconData.hIcon:=LoadIcon(0,IDI_EXCLAMATION)
- else FIconData.hIcon:=Application.Icon.Handle;
- Shell_NotifyIcon(NIM_MODIFY,@FIconData)
- end;
- //
- if (Msg.lParam = WM_LBUTTONDOWN)
- then
- begin
- Timer1.Enabled:=false;
- RestoreMainForm;
- end;
- end;
- //
- procedure TForm1.CreateTrayIcon(n:Integer);
- begin
- with FIconData do
- begin
- cbSize:=SizeOf(FIconData);
- wnd:=Handle;
- uID:=n;
- uFlags:=NIF_MESSAGE or NIF_ICON or NIF_TIP;
- uCallbackMessage:=WM_USER+123;
- hIcon:=Application.Icon.Handle;
- StrPCopy(szTip,Label3.Caption+' '+Label4.Caption)
- end;
- DoSomethingElse;
- Shell_NotifyIcon(NIM_ADD,@FIconData)
- end;
- //
- procedure TForm1.DeleteTrayIcon(n:Integer);
- begin
- with FIconData do
- begin
- cbSize:=SizeOf(FIconData);
- wnd:=Handle;
- uID:=n;
- end;
- Shell_NotifyIcon(NIM_DELETE, @FIconData);
- end;
- //
- procedure TForm1.Timer1Timer(Sender: TObject);
- begin
- FSecondIcon:= not FSecondIcon;
- if FSecondIcon
- then FIconData.hIcon:=LoadIcon(0,IDI_EXCLAMATION)
- else FIconData.hIcon:=Application.Icon.Handle;
- Shell_NotifyIcon(NIM_MODIFY,@FIconData)
- end;
-
- procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
- begin
- DeleteTrayIcon(100);
- Action:=caFree;
- end;
-
- end.
 |
Вопрос задал: 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Мб. Вот
|
Мини-форум вопроса
Мини-форум пуст.
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|