Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.08.21;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.48 MB
Время: 0.037 c
3-1121079216
llirik
2005-07-11 14:53
2005.08.21
rename column


14-1121602423
Blaster
2005-07-17 16:13
2005.08.21
Delphi 2005 - стоитли пробовать?


10-1099828711
John
2004-11-07 14:58
2005.08.21
Как заставить работать visiBroker


4-1120125721
TDionis
2005-06-30 14:02
2005.08.21
перехват mb_вторая_слева


14-1122640053
NeMaster
2005-07-29 16:27
2005.08.21
как двигать мышь





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский