Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
3-1182878418
Kley
2007-06-26 21:20
2007.11.04
из Excel в Access


1-1187521289
аааааа
2007-08-19 15:01
2007.11.04
винчестер


2-1192432990
СержК
2007-10-15 11:23
2007.11.04
Как узнать - сколько строк в документе Excel?


2-1192083904
_max_
2007-10-11 10:25
2007.11.04
эмулятор нажатия клавиш клавиатуры


2-1192047482
неугомонный
2007-10-11 00:18
2007.11.04
Маленькая помощь в скромной задачке :)





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