Главная страница
    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.053 c
1-1122583919
ronyn
2005-07-29 00:51
2005.08.21
Реестр и Install Shield


3-1121244094
Ирина
2005-07-13 12:41
2005.08.21
Запись


9-1111050921
cyborg
2005-03-17 12:15
2005.08.21
Dune 2


6-1115956502
@ndrew
2005-05-13 07:55
2005.08.21
Ошибки работы TSocket


4-1120426642
alex-drob
2005-07-04 01:37
2005.08.21
Блокировка клавиши Windows





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский