Страница 2 из 2
Добавлено: 11 июл 2006, 17:02
Eugie
Тут велосипед изобретать не надо, есть стандартное правило: передаваемые в поток данные должны быть валидны по кр.мере на момент входа в потоковую процедуру (а м.б. и до выхода из нее - все зависит от конкретики задачи).
Добавлено: 12 июл 2006, 08:40
LAngel
Eugie, хочется разобраться, почему переменная оказывается разрушена?
Сам часто работаю с потоками и не хочется наступать на грабли, часто пишу вызов подобным образом.
CreateThread вызывается из функции, в которой и объявлена локальная переменная, ссылка на структуру. На момент вызова CreateThread, она должна существовать, ибо память выделена, указатель на неё записан в переменную, явно она не уничтожалась, компилятор тоже не станет "самодействовать", ибо обращение к ней есть.
Насколько я понимаю, поток создается ещё до завершения функции CreateThread, так именно по этому, я считаю, что ссылка на структуру в памяти будет передана верно.
В чем я не прав?
Добавлено: 12 июл 2006, 15:19
Eugie
Дело в том, что поток запускается не "мгновенно". К моменту, когда управление будет передано потоковой процедуре, ты уже выйдешь из функции, из которой его запускал. А это в частности значит, что ее локальный контекст, или, как еще говорят, фрейм стека, будет разрушен. При этом скорее всего по адресам этих "бывших" локальных переменных окажется просто мусор. А может и не мусор

, но полагаться на это нельзя.
Добавлено: 15 июл 2006, 23:43
Evan
Очень интересно

Я поступил по другому: переменная Header стала не string а pchar,а код запуска потока я не менял. Спасибо всем кто откликнулся
Добавлено: 16 июл 2006, 04:34
Evan
Кстати в system.pas функция beginthread описана подобным образом т.е параметр это локальная переменная, а указатель высвобождается в самом потоке. По мойму нет никакой разницы глобальная переменная или локальная - главное что память выделена

Даже если использовать глобальную переменную в качестве параметра, в потоке все равно Header глючит

Добавлено: 18 июл 2006, 19:06
Eugie
Господа, должен признать, что был неправ: конечно же, локальную переменную типа указатель
можно передавать в CreateThread(). Главное, чтобы
блок памяти, на который она указывает, был валиден на момент входа в потоковую процедуру. Просто я неявно предполагал, что указатель на структуру данных передается в CreateThread() по ссылке (т.е. как var), а это не так. В противном случае предыдущий вывод был бы правильный.
Т.е. можно размещать соответствующую структуру в куче или в статической памяти, но нельзя
саму структуру описывать как локальную переменную:
Код: Выделить всё
type
TThreadParam = record
...
end;
PThreadParam = ^TThreadParam;
var gTp: TThreadParam;
function MyFunc: Cardinal;
var
pTp: PThreadParam;
lTp: TThreadParam;
begin
GetMem(pTp, sizeof(TThreadParam));
...
CreateThread(nil, 0, @GetAsync, pTp, 0, Result); //можно
CreateThread(nil, 0, @GetAsync, gTp, 0, Result); //можно
CreateThread(nil, 0, @GetAsync, lTp, 0, Result); //нельзя: локальная переменная lTp будет разрушена к моменту входа в GetAsync()
...
end;
Всё, надеюсь с этим тонким моментом разобрались
