![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Self в потоке
TUser © (2005-01-13 11:58:00)Вот такая проблема, даже не знаю, как описать. Есть дополнительный поток, там из Execute'а вызываются какие-то процедуры. И вот в одной из них написано
procedure TMyThread.MyProc;
begin
if FAnyField = afValue1 then
{do somthing}
else
{do other}
end;
FAnyField описан как FAnyField: (afValue1, afValue2). На строке 'if FAnyField = ...' поток почему-то вылетает (в смысле - терминируется). Выполняется OnTerminate.
Посмотрел в CPU. Там написано так
cmp byte ptr [eax+$60],$00
jz +<сколько-то>
Т.е. в eax должен быть адрес объекта, а $60 - смещение, по которому хранится значение FAnyField. Но в eax лежит ноль.
В другом месте потока, где также проверяется значение этого поля, компилятор пишет
cmp byte ptr [edi+$60],$00
причем в edi лежит какой-то нормальный адрес. Если подставить через CPU window в eax правильный адрес (в тот момент, когда там ноль), то эта строчка работает, хотя дальше, конечно, большие глюки, потому что где-то что-то я так понимаю очень глобально неправильно. Только вот не могу понять, что и где.
Пробовал написать
P:=DWord(@Self)
asm
mov eax, P; // ИМХО, это полный бред
end;
но компилятор перед сравнением подставляет в eax правильный (по его понятиям адрес), т.е. 0. Думал, может не синхронизировал я чего-нибудь, что положено было синхронизировать, но вроде бы все правильно. В чем может быть беда, подскажите, plz.
TUser (2005-01-13 14:48:00) [1]
> ну и как ты себе мыслишь это - переменной перечисляемого
> типа присвоить значение типа метод объекта ?
Никак не мыслю. Там еще и другая переменная есть (procedure of object). Раньше была просто переменной, в [12] я сделал ее полем класса TMyThread. Короче, исправился.
Digitman (2005-01-13 14:33:00) [2]
> TUser © (13.01.05 14:15) [15]
ну и как ты себе мыслишь это - переменной перечисляемоготипа присвоить значение типа метод объекта?
цитирую тебя :
> переменной прописать :=TMyThread.Proc1
Proc1 - это метод объекта класса TMyThread
"переменная" же , по твоим же словам, - перечислимого типа
ну дурь же ! ... согласись ?
TUser (2005-01-13 14:15:00) [3]Перечисляемого (afValue1, afValue2)
Digitman (2005-01-13 14:11:00) [4]
> переменной
переменной КАКОГГО типа ?
TUser (2005-01-13 14:07:00) [5]FAnyField - это поле класса TMyThread.
TUser (2005-01-13 14:06:00) [6]OnTerminate, конечно.
А баг действительно исправился. И как я раньше не знал, что если объявленной в модуле переменной прописать :=TMyThread.Proc1, то вызов этой Proc1 даже из другого метода TMyThread не приведет к тому, что Proc1 получит указатель на объект класса TMyThread?!
Alexander Panov (2005-01-13 14:04:00) [7]Что-то я не пойму.
FAnyField у тебя тип, но ты используешь именно тип, а не переменную?
Digitman (2005-01-13 14:03:00) [8]
> А разве OnExecute
что еще за OnExecute ? не знаю я такого события
KSergey (2005-01-13 13:58:00) [9]Есть подозрение, что проблема совсем не тут, ибо Self = nil - это бред какой-то.
К стати, а если написать явно if Self = nil then - вот прям и сработает? А то может ты просто несколько перегрелся по поводу Alt+Ctrl+C? ;) (без обид)
Ну либо где-то явно портится память, если это вдруг так. Если напрямую работы с памятью через указатели нет - возможно поможет Check Constraint
TUser (2005-01-13 13:56:00) [10]
> > Ну, и понятно - AV при обращении к одному из полей этого
>
> > объекта
>
>
> налицо явное противоречие.
Когда выполняется поток - то приходим в OnTerminate. Я просто попробовал вызвать все это дело в контексте основного потока (заменил resume на execute) - получил AV :) А разве OnExecute не должен вызываться при аварийном завершении потока?
TUser (2005-01-13 13:54:00) [11]Прошел отладчиком, посмотрел - в какой момент Self принимает
значение nil. Оказалось вот здесь
type
TMyThread = class(TThread)
FAnyField: (afValue1, afValue2);
...
procedure Proc1;
end;
implementation
type TStates = array of
record
... {разные поля}
OnEnter = procedure of object
end;
var States: TStates;
procedure TMyThread.Execute;
begin
...
if assigned(States[i]) then
// i = 0, такой элемент в массиве есть
States[i].OnEnter;
...
end;
procedure AddState(...);
begin
{добавляем элемент в массив States, если там еще такого нет}
end;
initialization
...
AddState (...Proc1)
...
end.
Т.е. поясню. Есть массив записей, в которых есть ссылки на некие процедуры объекта. Но, когда, я их их объекта вызываю, то у них self = nil. Наверное, так и должно быть, хотя они и описаны, как методы TMyThread.
Digitman (2005-01-13 13:53:00) [12]
> поток почему-то вылетает (в смысле - терминируется). Выполняется
> OnTerminate
> Ну, и понятно - AV при обращении к одному из полей этого
> объекта
налицо явное противоречие.
либо необработанное AV, приводящее к непредсказуемым рез-там, либо возбуждение OnTerminate - штатный и корректный факт корректного же завершения выполнения кода в теле Execute
у тебя происходит возбуждение OnTerminate - о каком же AV можно вести речь ? до возбуждения OnTerminate попросту дело не дойдет, если в ходе выполнения Execute будет возбуждено и никак не обработано непредусмотренное исключение, хотя бы то же самое AV
TUser (2005-01-13 13:45:00) [13]
> TMyThread - наследник TThread ?
Да.
> Не видно описания FAnyField. ЧТо это - тип или переменная?
FAnyField: (afValue1, afValue2);
Да, значение ему присваиваниется. Даже один раз проверяется, какое оно - и все вроде бы нормально. Только вот во время выполнения потока почему-то оказывается, что Self = nil, т.е. ноль. Ну, и понятно - AV при обращении к одному из полей этого объекта.
Verg (2005-01-13 13:42:00) [14]TMyThread - наследник TThread ?
Alexander Panov (2005-01-13 13:32:00) [15]Не видно описания FAnyField. ЧТо это - тип или переменная?
Alexander Panov (2005-01-13 13:31:00) [16]Мало что понятно из топика.
Но проверь, инициализируется ли FAnyField.
TUser (2005-01-13 13:26:00) [17]up