Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Изменить VMT


Страницы:   1 2 3

DevilDevil ©   (2007-07-23 10:20:00) 

Как бы то ни было странно, пишу такую функцию, типа PatchSomeClass(C : TClass) в теле которой происходит "подмена" адреса одной виртуальной функции.

Как я себе это представляю.

Для каждого класса существует некий массив указателей на функции (VMT). В каждом экземпляре такого класса хранится указатель на массив-VMT. Следовательно, получив указатель на VMT, зная смещение, я могу записать в этот массив произвольный указатель на функцию.

Все мои опыты приводят к AccessViolation. Есть ли какие нибудь предположения или наработки по данному поводу?


DevilDevil   (2007-07-26 13:42:00) [1]

> Инс ©   (26.07.07 13:19) [51]

Вы слишком агрессивно настроены


Инс   (2007-07-26 13:19:00) [2]


> нет, вызывать методы предка реально.

Реально - inherited. Более далекого предка - в принципе тоже реально. Побегать по VMT. Но вот только в хорошо спроецированной системе такого быть не должно. Если это требуется - значит система спроектирована плохо.


> А как это "по человечески" ?

По-человечески, это чтобы я, используя ваши юниты, не наткнулся на грабли, связанные с тем, что по неизвестным мне причинам принципы ООП не работают. В своем проекте, если что-то горит и нет времени переделывать всю структуру классов - ради бога, если работать будет. Другим же такую свинью не подсовывать.


DevilDevil   (2007-07-26 13:12:00) [3]

эээ ?

нет, вызывать методы предка реально. Сделать это можно описанным мной выше "способом". А как это "по человечески" ?


Инс   (2007-07-26 12:57:00) [4]


> Тогда нужно хранить ещё один массив записей (класс, AC,
> BD) ...

Нет, просто нужно не маяться дурью а делать все по-человечески. Либо не пускать подобные фишки за границы своего личного проекта.


DevilDevil   (2007-07-26 12:52:00) [5]

мда...

Тогда нужно хранить ещё один массив записей (класс, AC, BD) ...


Игорь Шевченко   (2007-07-26 12:33:00) [6]


> да вот я думаю, может не заморачиваться на них?
> всё равно, врядли их кто то использует.


Я использую активно. Я надеюсь, не одинок.
А вот что будет с теми, кто рассчитывает на штатное поведение, а наткнется на произведение такого изобретателя велосипеда с пятью квадратными колесами, я не берусь предположить


oxffff   (2007-07-26 12:25:00) [7]

Собственно не касаясь выбора способа решения.

А как же?

TCustomForm.AfterConstruction;
TDataModule.AfterConstruction;

TCustomForm.BeforeDestruction;
TDataModule.BeforeDestruction;

TComponent.BeforeDestruction;


DevilDevil   (2007-07-26 11:45:00) [8]

да вот я думаю, может не заморачиваться на них?
всё равно, врядли их кто то использует. Ни в одной книге я о них не слышал.


oxffff   (2007-07-26 11:21:00) [9]

To DevilDevil ©   (26.07.07 10:48) [43]

    lea edx, [eax + VMTOFFSET TObject.AfterConstruction] // edx - указатель на AC
    add eax, VMTOFFSET TObject.BeforeDestruction         // eax - указатель на BD

    mov ecx, AfterConstruction
    mov [edx], ecx
    mov ecx, BeforeDestruction
    mov [eax], ecx

А кто будет вызывать original AC, BD обработчики?


DevilDevil   (2007-07-26 10:48:00) [10]

> oxffff ©   (23.07.07 15:55) [20]

Спасибо, всё работает как надо.

Если что, вот полученный модуль: http://forum.mirgames.ru/index.php?act=Attach&type=post&id=3247

Ну и если хотите пообсуждать, вот ветка:
http://forum.mirgames.ru/index.php?act=ST&f=5&t=3986&st=0#entry62664


DevilDevil   (2007-07-24 17:46:00) [11]

я об этом уже писал.

делается это действительно просто: создаётся базовый класс, от которого в дальнейшем наследуются все мои классы.

DevilDevil ©   (23.07.07 17:00) [22]
Реальной какой-то пользы от такой функции я не жду ... , но:
1) интересно написать такую функцию
2) она может понадобиться


Инс   (2007-07-24 17:17:00) [12]

Все, что вы описали, элементарно делается и без пропатчивания VMT. Нужно просто хорошо продумать систему классов


DevilDevil   (2007-07-24 17:09:00) [13]

> Он попросил пример модификации VMT. Дали.  А что дальше.
>  Неизвестно.


Попробовать так и не успел; на днях попробую.

Ну как сказать... во-первых, просто хочется, чтобы объекты в любом случае удалялись. Во-вторых, есть такие объекты, который обязательно нужно удалить... и сделать это нужно в определённое время. Допустим вы пишите менеджер текстур; все текстуры в любом случае должны удалиться. Только сделать это они должны до удаления контекста устройства.

Как минимум, необходимость в хранении массива таких объектов есть. + Объект должен сам себя записывать в такой массив, и сам себя из него удалять.

Я хоть и не блеснул умением объяснять, надеюсь, вы хотя бы стали допускать необходимость в том механизме, который я стараюсь реализовать.


oxffff   (2007-07-24 11:59:00) [14]


> Не совсем понял, в чем вы меня убедить пытаетесь. Подводные
> камни в работе с интерфейсами безусловно есть. Тот пример
> что Вы привели - не единственный. Вот еще: http://www.delphikingdom.
> com/asp/viewitem.asp?catalogid=759 . Естественно работая
> с таким механизмом нужно знать и помнить как документированные
> фичи, так и эти самые подводные камни. Не зная всего этого
> при работе с интерфейсами очень легко нарваться.


Могу пояснить пример, который я вам привел.
Когда разрабатывали .NET было два взгляда на GC.
Один из этих вглядов разделяли COM разработчики.
Но им приводили в пример циклический список.
В итоге пошли по другому пути.

(Мое вольное повествование содержания статьи в интернете разработчиков .NET)

Поэтому я и привел вам этот пример.


oxffff   (2007-07-24 11:52:00) [15]


> А моя фраза "объект финализируется при выходе за область
> видимости" шла в противовес финализации при завершении приложения,
>  на мой взгляд практически бессмысленной в большенстве случаев.
>


Да я то собственно не связывал ваше и мое обсужение с темой автора.
В условий отсутствия полной и исчерпывающей информации сказать, что нужно автору темы я не представляю возможным.
Он попросил пример модификации VMT. Дали.  А что дальше. Неизвестно.


Инс   (2007-07-24 11:43:00) [16]


> oxffff ©   (24.07.07 11:33) [36]


Не совсем понял, в чем вы меня убедить пытаетесь. Подводные камни в работе с интерфейсами безусловно есть. Тот пример что Вы привели - не единственный. Вот еще: http://www.delphikingdom.com/asp/viewitem.asp?catalogid=759. Естественно работая с таким механизмом нужно знать и помнить как документированные фичи, так и эти самые подводные камни. Не зная всего этого при работе с интерфейсами очень легко нарваться.

А моя фраза "объект финализируется при выходе за область видимости" шла в противовес финализации при завершении приложения, на мой взгляд практически бессмысленной в большенстве случаев.


oxffff   (2007-07-24 11:33:00) [17]


>  b.abc:=nil; // Можно наоборот, не имеет значения


A и B не трогай.

Твое утверждение

>объект финализируется
> когда выходит за область видимости.

А если  ссылок на интерфейсы (т.е c,d) нет,  то объекты остануться.

ЕЖЕЛИ ты не приложишь усилий до выхода из области видимости "расцепить их". Но об этом надо задумываться!!!.

Поэтому интерфейсы это не панацея.


Инс   (2007-07-24 11:21:00) [18]


> После этого объекты продолжают существовать.

Естественно. Счетчик ссылок был два, стал - один.


> Как правильно освободить эти объекты?

Отвязать друг от друга. Например, так:

type
TABC=class(TinterfacedObject)
public
 abc:IINTERFACE;
 destructor Destroy; override;
end;

procedure TForm1.Button1Click(Sender: TObject);
var a,b:TABC;
  c,d:IUnknown;
begin
 a:=TABC.Create;
 b:=TABC.Create;
 a.abc:=b;
 b.abc:=a;
 c:=a;
 d:=b;
 c:=nil;
 d:=nil;
 b.abc:=nil; // Можно наоборот, не имеет значения
end;

{ TABC }

destructor TABC.Destroy;
begin
 Application.MessageBox('11','11',0);
 inherited;
end;


oxffff   (2007-07-24 11:13:00) [19]


> Инс ©   (24.07.07 10:16) [32]
>
> > Либо сам удалишь, вызвав DeleteObjects в нужный момент,
>  
> > либо он всё равно вызовется при finalization.
>
>
> А какой смысл освобождать память под экземпляр при завершении
> приложения? Когда процесс завершается система и так освобождает
> всю занятую им память. Разве что если в деструкторе выполняется
> какое-либо сохранение данных в файл или еще что-то в этом
> роде. А вот с интерфейсами все интереснее - объект финализируется
> когда выходит за область видимости. Другими словами, память
> будет освобождена не просто автоматически, но еще и сразу
> же, как в объекте отпадет необходимость.


Вот вам задача. Два объекта содержат интерфейсы друг друга.
Как правильно освободить эти объекты?

Вот пример

TABC=class(TinterfacedObject)
public
abc:IINTERFACE;
end;

procedure TForm1.Button1Click(Sender: TObject);
var a,b:TABC;
   c,d:IUnknown;
begin
a:=TABC.Create;
b:=TABC.Create;
a.abc:=b;
b.abc:=a;
c:=a;
d:=b;
c:=nil;
d:=nil;
end;

После этого объекты продолжают существовать.


Инс   (2007-07-24 10:59:00) [20]

Кстати, может еще стоит посмотреть, как управление временем жизни в компонентах организовано?


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо