powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Ann: Мониторинг создания объектов
7 сообщений из 7, страница 1 из 1
Ann: Мониторинг создания объектов
    #39914563
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Понадобилось мне узнать какие объекты созданы в данный момент в программе.

В итоге появился такой класс

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
type
  TPatchObject = class
  strict private
    type
      TData = array[0..4] of Byte;
      TSavedInfo = record
        Start: Pointer;
        Data: TData;
      end;
  strict private
    class var
      FAfterConstructionInfo: TSavedInfo;
      FBeforeDestructionInfo: TSavedInfo;
  strict private
    class procedure NewAfterConstruction(ASender: TObject); static;
    class procedure NewBeforeDestruction(ASender: TObject); static;
    class procedure WriteAddr(var ASavedInfo: TSavedInfo; AData: Pointer; ASize: Cardinal); static;
    class procedure PatchProc(out ASavedInfo: TSavedInfo; AReserved, ANewAddr: Pointer); static;
    class procedure UnpatchProc(var ASavedInfo: TSavedInfo); static;
  public
    class procedure Init;
    class procedure DeInit;
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
  end;

{ TPatchObject }

class procedure TPatchObject.NewAfterConstruction(ASender: TObject);
begin
  // Do notify construction
  ASender.AfterConstruction;
end;

class procedure TPatchObject.NewBeforeDestruction(ASender: TObject);
begin
  // Do notify destruction
  ASender.BeforeDestruction;
end;

class procedure TPatchObject.WriteAddr(var ASavedInfo: TSavedInfo;
  AData: Pointer; ASize: Cardinal);
var
  LOldProtection: Cardinal;
begin
  Win32Check(VirtualProtect(ASavedInfo.Start, ASize, PAGE_READWRITE, @LOldProtection));
  try
    Move(ASavedInfo.Start^, ASavedInfo.Data, ASize);
    Move(AData^, ASavedInfo.Start^, ASize);
  finally
    Win32Check(VirtualProtect(ASavedInfo.Start, ASize, LOldProtection, @LOldProtection));
  end;
  Win32Check(FlushInstructionCache(GetCurrentProcess, ASavedInfo.Start, ASize));
end;

class procedure TPatchObject.PatchProc(out ASavedInfo: TSavedInfo; AReserved, ANewAddr: Pointer);
asm
  mov edx, [esp]   // Return point

  sub ecx, edx     // Offset from return point to new proc
  sub edx, 5       // Start write address
  mov [eax], edx

  mov edx, esp
  sub esp, 8       // Reserve 8 byte in stack

  sub edx, 4
  mov [edx], ecx
  dec edx
  mov [edx], byte ptr $E8     // call offset
  mov ecx, 5

  call WriteAddr
  add esp, 8
end;

class procedure TPatchObject.UnpatchProc(var ASavedInfo: TSavedInfo);
var
  LData: TData;
begin
  LData := ASavedInfo.Data;
  WriteAddr(ASavedInfo, @LData, SizeOf(LData));
  FillChar(ASavedInfo, SizeOf(ASavedInfo), 0);
end;

class procedure TPatchObject.Init;
var
  LObj: TObject;
begin
  LObj := Create;
  LObj.Free;
end;

class procedure TPatchObject.DeInit;
begin
  UnpatchProc(FAfterConstructionInfo);
  UnpatchProc(FBeforeDestructionInfo);
end;

procedure TPatchObject.AfterConstruction;
asm
  lea eax, FAfterConstructionInfo
  mov ecx, offset NewAfterConstruction
  jmp PatchProc
end;

procedure TPatchObject.BeforeDestruction;
asm
  lea eax, FBeforeDestructionInfo
  mov ecx, offset NewBeforeDestruction
  jmp PatchProc
end;


Схема использования:

Отредактировать методы NewAfterConstruction, NewBeforeDestruction для своей нотификации.
Код: pascal
1.
2.
3.
TPatchObject.Init;  // Включили мониторинг
......
TPatchObject.DeInit;  // Выключили мониторинг


Идея: при создании объекта вызывается такая процедура
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
function _AfterConstruction(const Instance: TObject): TObject;
begin
  try
    Instance.AfterConstruction;
    Result := Instance;
  except
    _BeforeDestruction(Instance, 1);
    raise;
  end;
end;

я поднимаюсь вверх по стеку и заменяю выделенную строку таким вызовом
Код: pascal
1.
TPatchObject.NewAfterConstruction(Instance)


Аналогично для _BeforeDestruction

Разрабатывалось и тестировалось на Delphi XE3 при компиляции под x86. Под x64 в текущем виде работать гарантировано не будет. Под другие версии Delphi скорее всего заработает без вопросов.


С уважением, Vasilisk
...
Рейтинг: 0 / 0
Ann: Мониторинг создания объектов
    #39914572
ziv-2014
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Ann: Мониторинг создания объектов
    #39914730
Фотография Квейд
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

наверное, так можно сократить чуть

Код: pascal
1.
2.
3.
4.
class procedure TPatchObject.Init;
begin
  Create.Free;
end;
...
Рейтинг: 0 / 0
Ann: Мониторинг создания объектов
    #39914845
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Квейд
наверное, так можно сократить чуть
Можно. Но отлаживать удобнее двумя операторами :)
...
Рейтинг: 0 / 0
Ann: Мониторинг создания объектов
    #39915726
KtoI
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А чё у формы\панели уже не модно спрашивать Components ?
...
Рейтинг: 0 / 0
Ann: Мониторинг создания объектов
    #39915739
DimaBr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KtoI
А чё у формы\панели уже не модно спрашивать Components ?

Если владелец - NIL то не у кого спрашивать
...
Рейтинг: 0 / 0
Ann: Мониторинг создания объектов
    #39915804
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KtoI
А чё у формы\панели уже не модно спрашивать Components ?
Код: pascal
1.
2.
List := TStringList.Create;
List.AddObject('One', TMemoryStream.Create);


Что и у кого будете спрашивать?
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Ann: Мониторинг создания объектов
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]