Форум: "Начинающим";
Текущий архив: 2007.11.04;
Скачать: [xml.tar.bz2];
Внизотличия Assign от p<>nil Найти похожие ветки
← →
денизко (2007-10-09 17:24) [0]Объясните дураку зачем нужна ф-ция Assign, если можно написать
if p<>nil then ...
И как все таки узнать был ли убит объект, если после вызова деструктора Free, переменная-объект по-прежнему не nil и указывает на недоступный кусок памяти?
← →
clickmaker © (2007-10-09 17:29) [1]Assigned(P) corresponds to the test P<> nil for a pointer variable, and @P <> nil for a procedural variable (c) F1
> переменная-объект по-прежнему не nil
FreeAndNil()
← →
Сергей М. © (2007-10-09 17:31) [2]
> ачем нужна ф-ция Assign, если можно написать
> if p<>nil then ...
>
Встречный вопрос - зачем писать
if p<>nil then ...
если можно написать
if Assigned(p) then ...
?
На первое время считай, что разницы никакой.
> узнать был ли убит объект
Если возникло исключение EAccessViolation или EInvalidPointer, то объект 100%-но "убит".
Вероятность же невозникновения одного из этих исключений при гарантированно "убитом" объекте ничтожно мала.
← →
денизко (2007-10-09 17:36) [3]
> clickmaker ©
Спасибо за ответ.
Хелп я читал и с FreeAndNil знаком.
Т.е. получается что Assigned только для того и нужна, чтобы в нее можно было пихать как указатели так переменные процедурного типа? Хм, лично мне не сложно и ручками написать @P <> nil, но это не важно... С этим понятно..
Второй вопрос открыт: известны ли кому-нибудь способы, как узнать был ли убит объект, если он был убит НЕ FreeAndNil а банальным деструктором Free?
← →
Сергей М. © (2007-10-09 17:43) [4]
> известны ли кому-нибудь способы, как узнать был ли убит
> объект
Нет иных способов, нежели перехват исключения.
Да и не надо ничего узнавать, просто не следует допускать "убийство" объекта без соответствующей немедленной коррекции всех существующих ссылок на него.
← →
Правильный Вася (2007-10-09 17:48) [5]
> ф-ция Assign
вообще-то это метод, и делает он вещи прямо противоположные описанным тобой
← →
денизко (2007-10-09 17:49) [6]Тьфу, не Assign, Assigned конечно.. торопился..
> Сергей М.
> Если возникло исключение EAccessViolation
т.е. бороться с ним в блоке try except? смущает громоздкий код:
если б Assigned позволяла определить существование объекта я бы обошелся одной лаконичной строкой:if Assigned(p) then p.DoIt;
с try except будет 4:
try
p.DoIt;
except
end;
можно конечно все в одну уложить но... не нравится и все тут! :)
← →
Ega23 © (2007-10-09 17:55) [7]
> Второй вопрос открыт: известны ли кому-нибудь способы, как
> узнать был ли убит объект, если он был убит НЕ FreeAndNil
> а банальным деструктором Free?
Перехват исключения.
А вообще - просто не следует такого допускать ещё при проектировании.
И, кстати, FreeAndNil(Obj) можно тупо заменить на
Obj.Free;
Obj := nil;
← →
clickmaker © (2007-10-09 18:00) [8]
> можно тупо заменить на
> Obj.Free;
> Obj := nil;
в многопоточном можно нарваться, хотя и маловероятно
← →
Ega23 © (2007-10-09 18:02) [9]
> в многопоточном можно нарваться, хотя и маловероятно
Это как?????
← →
clickmaker © (2007-10-09 18:07) [10]procedure FreeAndNil(var Obj);
var
Temp: TObject;
begin
Temp := TObject(Obj);
Pointer(Obj) := nil;
Temp.Free;
end;
сравни последовательность операций.
Представь, что деструктор начал выполняться, а другой поток с чистой совестью, проверив, что <> nil, полез работать с объектом...
← →
Суслик © (2007-10-09 18:25) [11]
> [9] Ega23 © (09.10.07 18:02)
> > в многопоточном можно нарваться, хотя и маловероятно
> Это как?????
я нарывался как в [10] описано.
------------
по сабжу - я не пишу Assigned никогда, всегда <> nil пишу.
удобней мне так
← →
MetalFan © (2007-10-09 19:15) [12]а как вам нечто такое?
function CheckIsFreed( AObject: TObject ): Boolean;
var
Signature: PLongInt;
P: Pointer;
begin
P := AObject;
Result := P = nil;
if Result then Exit;
Signature := PLongInt(LongInt(P) - 4);
Result := Signature^ = 1;
end;
← →
MetalFan © (2007-10-09 19:18) [13]нет, лучше такое:
function CheckIsFreed( AObject: TObject ): Boolean;
var
Signature: PLongInt;
P: Pointer;
begin
P := AObject;
Result := P = nil;
if Result then Exit;
Signature := PLongInt(LongInt(P) - 4);
Result := IsBadReadPtr( Signature, 4 );
if result then Exit;
Result := Signature^ = 1;
end;
и тесткод:procedure TForm1.Button1Click(Sender: TObject);
var
lSL : TStringList;
begin
Integer(lSL) := 123123123;
ShowMessage( BoolToStr( CheckIsFreed( lSL), True ));
lSL := TStringList.Create;
ShowMessage( BoolToStr( CheckIsFreed( lSL), True ));
lSL.Free;
ShowMessage( BoolToStr( CheckIsFreed( lSL), True ));
end;
← →
Johnmen © (2007-10-09 19:41) [14]Солидарен с Суслик © (09.10.07 18:25) [11], так удобней.
← →
денизко (2007-10-09 20:26) [15]
> MetalFan ©
О! А можно поподробней? Что находится по адресу LongInt(P) - 4
← →
MetalFan © (2007-10-09 23:02) [16]
> Что находится по адресу LongInt(P) - 4
чес говоря я привел код, который работает только в D2006...
как оказалось, в разных версиях делфи по-разному менеджер памяти работает...
← →
Суслик © (2007-10-10 00:13) [17]
> чес говоря я привел код, который работает только в D2006.
> ..
> как оказалось, в разных версиях делфи по-разному менеджер
> памяти работает...
не надо такими вещами заниматься - все равно 100проц. гарантии нет.
← →
evvcom © (2007-10-10 08:43) [18]
> все равно 100проц. гарантии нет
потому занятие такой фигней, так или иначе будет регулярно приводить к плавающим ошибкам (ошибка то есть, то нет). Если у тебя одна ссылка на объект, то используй FreeAndNil и не морочь людям голову своими вопросами, если ссылок на объект несколько, используй FreeNotification.
← →
денизко (2007-10-10 09:14) [19]
> evvcom ©
>и не морочь людям голову своими вопросами,
Дружище, извини ради Бога! Я то по простоте душевной думал что форум для любых вопросов по Делфи! Я ж не знал что он только для "правильных", т.е. таких вопросов, кот. не будут людям морочить голову.
Приношу свои извинения всем, кому, заморочил голову :)) Я не нарочно :)
По теме:
я вот тоже сначала пытался IsBadReadPtr использовать, только я пытался читать непосредственно тот кусок памяти, на который указывает переменная-объект. Но IsBadReadPtr(p) исправно возвращала false, т.е. память прекрасно читалась.
А вообще почему я задался этим вопросом:
меня удручает отсутствие такого инструмента, кот. мог бы показать мне состояние объекта: жив он или нет. Я понимаю, есть FreeAndNil, есть FreeNotification, можно в конце концов вручную вести списки "учета", где отмечать, что такой-то объект был только что уничтожен, а эти еще живы и т.д. НО! Почему бы не иметь под рукой такую полезную функцию, скажем CheckIsFreed, как обозвал ее MetalFan ? Ну удобно же! Разве нет?
Я пытался сделать ее сам, ничего не получилось. Потому и обратился к народу: кто интересовался подобным?
← →
Leonid Troyanovsky © (2007-10-10 09:25) [20]
> денизко (10.10.07 09:14) [19]
http://delphimaster.net/view/2-1190379982/
--
Regards, LVT.
← →
Ping (2007-10-10 09:36) [21]Я понимаю, есть FreeAndNil, есть FreeNotification, можно в конце концов вручную вести списки "учета", где отмечать, что такой-то объект был только что уничтожен, а эти еще живы и т.д. НО! Почему бы не иметь под рукой такую полезную функцию, скажем CheckIsFreed, как обозвал ее MetalFan ? Ну удобно же! Разве нет?
Интерфейсы. Подсчет ссылок и самоудаление при отсутствии оных. Плюс "бонус" в виде строгой инкапсуляции.
← →
денизко (2007-10-10 12:28) [22]
> Leonid Troyanovsky
> http://delphimaster.net/view/2-1190379982/
Спасибо за ссылку. Внимательно прочитал.
Но я озадачен немного другим вопросом, нежели Kolan. Он хотел чтобы при деструкторе все ссылки на объект принимали значение nil. А меня всего лишь интересует средства проверки состояния объекта, на кот. ссылается ссылка: был он уничтожен или нет. Или в общем случае даже так: могу ли я работать (вызывать методы и читать свойства) с объектом, на кот. указывает некая ссылка?
Вот уважаемый MetalFan привел интересный для меня код, но говорят, что работает лишь в D2006... Я в своей D7 посмотрел что происходит при вызове Free, оказалось, что в некоторых случаях Longint(p)+8 равен 1 и после деструктора зануляется, и Longint(p)+12 равен 4 и также зануляется... Но это все "нелегально", может сработать в паре тройке случаев...
← →
Leonid Troyanovsky © (2007-10-10 12:33) [23]
> денизко (10.10.07 12:28) [22]
> Но я озадачен немного другим вопросом, нежели Kolan. Он
> хотел чтобы при деструкторе все ссылки на объект принимали
> значение nil. А меня всего лишь интересует средства проверки
> состояния объекта, на кот. ссылается ссылка: был он уничтожен
> или нет
Ну, на самом деле, оба эти желания совпадают, т.е.,
если ссылка nil, то объекта не существует.
> Или в общем случае даже так: могу ли я работать (вызывать
> методы и читать свойства) с объектом, на кот. указывает
> некая ссылка?
Если ссылка валидна, то можешь.
--
Regards, LVT.
← →
Anatoly Podgoretsky © (2007-10-10 13:03) [24]> Leonid Troyanovsky (10.10.2007 12:33:23) [23]
> если ссылка nil, то объекта не существует.
Может и существует, но обратиться к нему нельзя.
P := TObject.Create;
P := nil;
← →
Суслик © (2007-10-10 13:08) [25]вообще в рамках FastMM (манагер памяти в дельфи2007 и 2006) есть такая фишка, как full debug mode.
При его включенности память после дестроя забивается неким мусором ($08 кажется). VMT подменяется. В итоге вызовы вирт. методов всегда 100% определяют жив объект или нет. Ясно дело, что такой режим тормозной очень. Но искать места вызова мертвых объектов можно.
Для невиртуальных методов это ясное дело не работает. Т.е. обращение к памяти мертвого объекта никак не отловишь.
← →
Leonid Troyanovsky © (2007-10-10 13:10) [26]
> Anatoly Podgoretsky © (10.10.07 13:03) [24]
> Может и существует, но обратиться к нему нельзя.
Да, конечно.
Я просто имел ввиду, что если б исполнилось желание Коляна,
то и уважаемому денизко было б просто проверять существование.
--
Regards, LVT.
← →
Sha © (2007-10-10 15:13) [27]> денизко
Из того, что память занята никак не следует,
что там лежит тот же объект.
← →
ZeroDivide © (2007-10-10 16:00) [28]
Суслик © (09.10.07 18:25) [11]
по сабжу - я не пишу Assigned никогда, всегда <> nil пишу.
удобней мне так
Так уж и никогда? :)
Для эвентов пишешь!
var
MyKeyEvent: TKeyEvent;
begin
//Ругнется здесь, хотя по сути - тоже указатель на процедуру объекта
if MyKeyEvent <> nil then
MyKeyEvent := nil;
//Ок
if Assigned(MyKeyEvent) then
MyKeyEvent := nil;
← →
Суслик © (2007-10-10 16:23) [29]
> [28] ZeroDivide © (10.10.07 16:00)
> Суслик © (09.10.07 18:25) [11]
> по сабжу - я не пишу Assigned никогда, всегда <> nil пишу.
> удобней мне так
> Так уж и никогда? :)
> Для эвентов пишешь!
у меня нет ивентов (не люблю их) - обычно классы целые передаю в вирт. методами.
потом как-то можно это делать, так кажетсяif @MyKeyEvent <> nil then
← →
Сергей М. © (2007-10-10 16:28) [30]
> денизко (10.10.07 12:28) [22]
> меня всего лишь интересует средства проверки состояния объекта,
> на кот. ссылается ссылка
Нет объекта - нет и и его "состояния".
Более того, на месте "убитого" объекта может оказаться совсем другой объект, и тогда дальнейшее поведение не учитывающего такую ситуацию алгоритма непредсказуемо.
← →
Alkid © (2007-10-11 08:48) [31]Я пользовался такой фишкой: создавал поле, в котором хранил сигнатуру и невиртуальный метод, которые проверяет IsBadPtr, а потом проверяет сигнатуру. В конструкторе сигнатура инициализируется, в деструкторе затирается.
Если нет уверенности, что ссылка указывает на валидный объект, можно проверять таким образом. Недостаток один - из-за отсутствия в Дельфи множественного наследования эту фишку нельзя реализовать в отдельном классе и привносить в классы сторонней иерархии, но можно основать свою иерархию на классе с такой возможность.
Ещё замечу, что я такой приём юзал только для отладки. А вообще считаю, что писать программы надо так, что бы было ясно кто и когда кого создаёт и удаляет.
← →
Leonid Troyanovsky © (2007-10-11 09:28) [32]
> Alkid © (11.10.07 08:48) [31]
> сигнатуру и невиртуальный метод, которые проверяет IsBadPtr
Дельфийский менеджер может повторно использовать
освобожденную объектом память для другого.
--
Regards, LVT.
← →
Alkid © (2007-10-11 10:48) [33]
> Дельфийский менеджер может повторно использовать
> освобожденную объектом память для другого.
Да, такая вероятность есть, хотя и невелика.
← →
Anatoly Podgoretsky © (2007-10-11 13:23) [34]> Alkid (11.10.2007 10:48:33) [33]
А согласно Мерфи - велика, да и нафига нужна программа, которая зависит от погоды на Марсе.
← →
ANTPro © (2007-10-11 16:29) [35]> [33] Alkid © (11.10.07 10:48)
[-------0] Информация : Экземпляр GlobalLog класса TLog создан.
[------27] Информация : Экземпляр RenderTime класса TPerformance создан.
[-------8] Информация : Экземпляр FPSCounter класса TPerformance создан.
[-------8] Отладка : Экземпляр $00144488 класса TUserInput создан.
[-------9] Отладка : Экземпляр $00147DD8 класса TProcArray создан.
[-------8] Отладка : Экземпляр $00145F28 класса TRender создан.
[------81] Отладка : Экземпляр $00146020 класса TWindow создан.
[------11] Отладка : Экземпляр $00150F50 класса TLights создан.
[-------8] Отладка : Экземпляр $0014D810 класса TLight создан.
[-------8] Отладка : Экземпляр $001440C8 класса TCore создан.
[-------9] Отладка : Экземпляр $00152FD0 класса TCamera создан.
[-------8] Отладка : Экземпляр $001530B0 класса TCamera создан.
[-------8] Отладка : Экземпляр $001530A0 класса TSkyBox создан.
[-------9] Отладка : Экземпляр $001530D8 класса TObject3D создан.
[-------8] Отладка : Экземпляр $00153168 класса TFileStream создан.
[-------9] Отладка : Файл D:\Downloads\ANTPro\spacewar[5]\SpacePlane.bin открыт/создан.
[------25] Отладка : Экземпляр $00153168 класса TFileStream разрушен.
[------24] Отладка : Экземпляр $00160BE8 класса TCamera создан.
[-------9] Отладка : Экземпляр $00153050 класса TModel создан.
[-------8] Информация : Экземпляр DebugCounter класса TPerformance создан.
[-------8] Информация : Среднее время выполнения счетчика DebugCounter: 0 ms
[-------9] Информация : Экземпляр DebugCounter класса TPerformance разрушен.
[----1095] Отладка : Экземпляр $00163908 класса TFileStream создан.
[-------4] Отладка : Файл SpacePlane.bin открыт/создан.
[------26] Отладка : Экземпляр $00163908 класса TFileStream разрушен.
[---10832] Отладка : Экземпляр $00163908 класса TFileStream создан.
[------29] Отладка : Файл SpacePlane.bin открыт/создан.
[------25] Отладка : Экземпляр $00163908 класса TFileStream разрушен.
[---16824] Отладка : Экземпляр $00163908 класса TFileStream создан.
[------26] Отладка : Файл SpacePlane.bin открыт/создан.
[------26] Отладка : Экземпляр $00163908 класса TFileStream разрушен.
[---13143] Отладка : Экземпляр $00163908 класса TFileStream создан.
[------25] Отладка : Файл SpacePlane.bin открыт/создан.
[------25] Отладка : Экземпляр $00163908 класса TFileStream разрушен.
[----5764] Отладка : Экземпляр $00163908 класса TFileStream создан.
[-------8] Отладка : Файл SpacePlane.bin открыт/создан.
[------25] Отладка : Экземпляр $00163908 класса TFileStream разрушен.
[---11930] Отладка : Экземпляр $00145E30 класса TGame разрушен.
[------22] Отладка : Экземпляр $00152FD0 класса TCamera разрушен.
[-------9] Отладка : Экземпляр $001530B0 класса TCamera разрушен.
[-------8] Отладка : Экземпляр $001530A0 класса TSkyBox разрушен.
[-------8] Отладка : Экземпляр $001530D8 класса TObject3D разрушен.
[-------9] Отладка : Экземпляр $00160BE8 класса TCamera разрушен.
[-------8] Отладка : Экземпляр $00153050 класса TModel разрушен.
[-------9] Отладка : Экземпляр $001440C8 класса TCore разрушен.
[-------8] Отладка : Экземпляр $00144488 класса TUserInput разрушен.
[-------8] Отладка : Экземпляр $00147DD8 класса TProcArray разрушен.
[-------9] Отладка : Экземпляр $0014D810 класса TLight разрушен.
[-------8] Отладка : Экземпляр $00150F50 класса TLights разрушен.
[-------8] Отладка : Экземпляр $00145F28 класса TRender разрушен.
[-------9] Отладка : Экземпляр $00146020 класса TWindow разрушен.
[-------8] Информация : Среднее время выполнения счетчика RenderTime: 16 ms
[-------8] Информация : Экземпляр RenderTime класса TPerformance разрушен.
[-------9] Информация : Среднее время выполнения счетчика FPSCounter: 6421 ms
[-------8] Информация : Экземпляр FPSCounter класса TPerformance разрушен.
[-------8] Информация : Экземпляр GlobalLog класса TLog разрушен.
:)
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2007.11.04;
Скачать: [xml.tar.bz2];
Память: 0.58 MB
Время: 0.045 c