Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.08.21;
Скачать: CL | DM;

Вниз

Проблема с видимостью полей объекта   Найти похожие ветки 

 
sunsay ©   (2005-07-28 13:27) [0]

Привет всем мастерам!
Кто-нить сталкивался со следующей проблемой?
Только сейчас (точнее, уже дня три "танцы с бубном") наткнулся в своём проекте, раньше не замечал...
При работе метода объекта почему-то не видно полей (переменных) этого объекта и приложение вылетает при попытке доступа к любому полю.
Сейчас попробую объяснить подробнее:
В начале работы моей программы некоторые объекты "регистрируют" свои обработчики в менеджере сообщений на какие сообщения они будут реагировать, допустим:


type
TMailSender = class (TBaseClass)
//...
 FSomeVariable: String;
 procedure SomeMethod;
 procedure OnSendMail(var Msg: TCustomMessage);
//...
end;

constructor TMailSender.Create(aLogFileName: String);
begin
 FLogFileName := aLogFileName;
 MessageManager.RegisterMessageHandler("mm_send_mail", OnSendMail);
end;


в классе менеджера сообщений (TMessageManager), описание этой процедуры (RegisterMessageHandler) выглядит так:
вообщем эта процедура определенным образом сохраняет указатель обработчика @Handler:


type TMessageHandler = procedure (var Msg: TCustomMessage) of object;

function TMessageManager.RegisterMessageHandler(MessageName: String; Handler: TMessageHandler): Boolean;
var P: Pointer;
...
 P := @Handler;


Потом во время работы программы, какай-то объект создал сообщение и вызывает MessageHandler.DispatchMessage, в параметре передает сообщение.
в DispatchMessage смотрим какое имя у сообщение Msg.Name, ищем какие обработчики были на это имя зарегистрированны
и запускаем один обработчик вот так:


procedure TMessageManager.DispatchMessage(var Msg: TCustomMessage);
var Handler: TMessageHandler;
...
 @Handler := P;
 Handler(Msg);


Обработчик запускается замечательно - все локальные переменные работают, методы объекта вызываются, но при попытке получить доступ к полям обекта - вылетает программа с 216 ошибкой.


procedure TMailSender.OnSendMail(var Msg: TCustomMessage);
begin
 Self.SomeMethod;            // работает замечательно
 FSomeVariable := "sdsdsd";  // ! ошибка - почему то в отладчике в watches написано inaccessible value
end;


Если кто-то досюда дочитал, уже спасибо :) А если ещё и понял что-нибудь, то тогда поделитесь мыслями или задайте наводящие вопросы, если что, могу код переслать.
Медленно но верно начинаю нервничать, у меня дергается правый глаз и уходит две пачки сигарет в день :)))

Одна просьба, не спрашивать меня зачем я так делаю (в смысле общения объектов через сообщения) - долго объяснять...


 
Digitman ©   (2005-07-28 13:46) [1]


> Self.SomeMethod


зачем Self ? в данном контексте компилятор и так поймет, что речь идет о текущем экземпляре - ты ведь в теле этого метода к иным экз-рам данного класса не обращаешься, только к текущему


> ошибка - почему то в отладчике в watches написано inaccessible
> value


т.е. то что "в watches написано" и есть по-твоему не иначе как ошибка ?


 
Leonid Troyanovsky ©   (2005-07-28 13:48) [2]


> sunsay ©   (28.07.05 13:27)  



> var P: Pointer;
> ...
>  P := @Handler;


Какое такое P? Да еще и Pointer.
Ведь regular procedure vs method of class - две большие
разницы. Используй уж лучше поля для ссылок на методы,
на манер TNotifyEvent.

--
Regards, LVT.


 
evvcom ©   (2005-07-28 13:48) [3]


> Self.SomeMethod;

Достаточно просто SomeMethod;
Очень похоже на то, что объекта уже нет. А что в Watch показывает Self и Pointer(Self)?


 
evvcom ©   (2005-07-28 13:52) [4]

Да, кстати, точно. См. [2], ты теряешь Self в P := @Handler;


 
sunsay ©   (2005-07-28 16:46) [5]

Ну Self там действительно необязательно - так, написал, взгрустнулось наверное, не в этом фишка...
TO evvcom> объект есть, это сто пудово - его никто не освобождает...
TO Leonid Troyanovsky> то есть если я просто запоминаю указатель на метод объекта, а потом пытаюсь вызвать её - такое не пройдет и я типа теряю связь с самим объектом?


 
Leonid Troyanovsky ©   (2005-07-28 16:56) [6]


> TO Leonid Troyanovsky> то есть если я просто запоминаю указатель
> на метод объекта, а потом пытаюсь вызвать её - такое не
> пройдет и я типа теряю связь с самим объектом?


Да.
Размер TMethod - 8, а Pointer -4.
Т.е., указатель на объект теряется.

--
Regards, LVT.


 
sunsay ©   (2005-07-28 17:03) [7]


> Размер TMethod - 8, а Pointer -4.
> Т.е., указатель на объект теряется.


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


uses windows;

type
 // вот наш класс
 TSampleObject = class
 public
   Variable: String;
   procedure Method;
 end;

// вот наш метод
procedure TSampleObject.Method;
begin
 Variable := "Sample";
 MessageBox(0, PChar(Variable), nil, MB_OK);
end;

type
 TMethod = procedure of object;
var
 Method: TMethod;
 SampleObject: TSampleObject;
 P: Pointer;
begin
 SampleObject := TSampleObject.Create;   // создаем объект
 Method := SampleObject.Method;          // вот наш метод
 P := @Method;      // запоминаем адрес метода
 @Method := nil;    // указатель на метод обнуляем, то есть если
                    // если попробуем вызвать сейчас Method - всё нафиг вылетит
 @Method := P;      // возвращаем на место (из Pointer"а, кстати, который 4 байта)
 Method;            // всё чудесно работает, и к Variable я почему-то имею доступ
 SampleObject.Free;                      // освобождаем объект    
end.


 
han_malign ©   (2005-07-28 17:19) [8]

>возвращаем на место (из Pointer"а, кстати, который 4 байта)
- nil, кстати, тоже 4 байта - второе поле структуры Method(где лежит тот самый указатель на экземпляр) не обнуляется...

System.pas:
 TMethod = record
   Code, Data: Pointer;
 end;

Так что - без всяких "почему-то"...


 
han_malign ©   (2005-07-28 17:21) [9]

короче, поменяй Pointer на TMessageHandler - и будет тебе щастье...


 
sunsay ©   (2005-07-28 17:24) [10]


> короче, поменяй Pointer на TMessageHandler - и будет тебе
> щастье...


круто... пойду проверять.


 
sunsay ©   (2005-07-28 17:38) [11]

Пасиб всем огромный! Разобрался.



Страницы: 1 вся ветка

Текущий архив: 2005.08.21;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.045 c
3-1121233551
silvestr
2005-07-13 09:45
2005.08.21
Проблема при вставке записи с помощью хранимой процедуры


3-1121166891
Ирина
2005-07-12 15:14
2005.08.21
Сортировка


4-1119697602
Darkwing
2005-06-25 15:06
2005.08.21
Асинхронный I/O


4-1119951512
Gear
2005-06-28 13:38
2005.08.21
Окна


14-1122908419
lookin
2005-08-01 19:00
2005.08.21
Удивительное место на Земле - остров Питкерн