Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.11.04;
Скачать: CL | DM;

Вниз

отличия 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;
Скачать: CL | DM;

Наверх




Память: 0.59 MB
Время: 0.026 c
15-1191319495
Azize
2007-10-02 14:04
2007.11.04
Посветуйте литературу


15-1191573275
Kostafey
2007-10-05 12:34
2007.11.04
Программное создание источника данных


2-1191920499
r.o.o.t
2007-10-09 13:01
2007.11.04
Закрытие формы


2-1192270081
Новичек
2007-10-13 14:08
2007.11.04
Состояние DataSet.


6-1172597893
Muhh
2007-02-27 20:38
2007.11.04
Помогите, плиз, со скачиванием файла из интернета.