Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Object = nul ???


Автор: Illusion Dolphin 29.8.2003, 09:31
Не раз сталктваюсь с проблемой, что объект, разрушенный при помощи такого:
object.free
после при проверки на nul выдаёт false, но при попытке к нему обратиться тоже assecc denied или тому подобное. Поэтому подскажите, пожалуйста, как дополнить код:
If object<>nul then
object.property:=value
чтобы не возникало ошибок?

Автор: stab 29.8.2003, 12:11
для освобождения используй: FreeAndNil(object);

Автор: <Spawn> 29.8.2003, 12:13
Или делай
Код
Object.Free;
Object:=nil;

Автор: Illusion Dolphin 29.8.2003, 14:40
Гы... дело не в том, как выгрузить (это я знаю), а как узнать, выгружен ли!!! Очень хочется знать!

Автор: stab 29.8.2003, 15:18
ну дык, FreeAndNil(object); делает так:

object.Free;
object := nil;

равенство object nil'у и есть признак его выгружености, а если делать просто Free то object сохраняет указатель на объект, а объекта самого нет уже и тогда и появляеться Access violation... короче везде где у тя стоит object.Free замени на FreeAndNil(object);

Автор: Akella 29.8.2003, 16:53
А можно сделать так
Код
Form1:=TForm1.Crerate(self);
if Form1.ShowModal=mrOK then begin
...
end;
//вместо Form1.Free ставим
FreeAndNil(Form1);

Автор: p0s0l 29.8.2003, 18:32
а можно так
try
object1.SomeMethod
except
// объект выгружен
end;

Автор: Illusion Dolphin 29.8.2003, 20:31
Цитата
а можно так
try
object1.SomeMethod
except
// объект выгружен
end;


Почти то что нужно (cully и dsergey предлагали не способ определить, nul или нет, а установки nul), но хотелось бы чтобы не было исключений! Есть ли способ типа:

if что_то(object) then showmessage('объект не создан!');

Может, можно посмотреть размер памяти, занимаемый объектом и емли он ноль, то он выгружен? Как-нибудь это можно сделать?

Автор: altarasjuk 30.8.2003, 18:53
а не проще ли
Код

 if Assigned(obj) then
   obj.Foo();

?
Метод assigned вернёт true если объект существует и false если его уже кто-то "убил".

Автор: stab 30.8.2003, 21:16
Illusion Dolphin все дело в объектной модели дельфи -- объект и указатель на него ни как между собой не связаны, т.е. по сути две следующие записи эквивалентны:

Код

type
TMyClass = class
 f1: Integer;
 procedure Inc;
end;

......

procedure Inc;
begin
Self.f1 := Self.f1 + 1;
end;

......

var
o1: TMyClass;

o1 := TMyClass.Create;
o1.Inc;
o1.Free;

///////////////////////////////////

type
TMyClassRecord = record
 f1: Integer;
end;
TMyClass = ^TMyClassRecord;

procedure Inc(Self: TMyClass);
begin
Self.f1 := Self.f1 + 1;
end;

.........

var
o1: TMyClass;

New(o1);
Inc(o1);
Dispose(o1);



а как можно по указателю на область памяти узнать действительно ли это те данные которые нужны? да ни как smile.gif конечно есть вариант, что указатель указывает на уже НЕвыделенную память тогда будет эксепшен, но скорее всего указатель будет указывать на память, которая уже используется под данные другого объекта, т.е. просто в полях объекта будут левые значения и вместо ожидаемых действий при вызове методов будет получаться что-то совсем не то.

Как решение проблемы можно посоветовать использование COM-объектов -- они сами выгружаются когда на них нет больше ни одной ссылки.

Автор: stab 30.8.2003, 21:20
по поводу Assigned:

Цитата
Assigned returns false if P is nil, true otherwise.
© Delphi Help

Автор: p0s0l 31.8.2003, 02:59
еще вариант: первые 4 байта = адресу класса объекта. Если ты знаешь класс объекта то можно узнать, инициализирован ли объект, правда все равно существует возможность ложного определения. А с памятью тут ничего не придумать - я смотрел, в Delphi память выделяется кусками, а в одном куске может сидеть несколько объектов. Не зная начального адреса выделенной памяти ничего не узнать...

Автор: stab 31.8.2003, 12:15
Цитата
еще вариант: первые 4 байта = адресу класса объекта. Если ты знаешь класс объекта то можно узнать, инициализирован ли объект...


т.е. просто делать:
Код

if object is TMyObjectClass then
begin
...
end;

Автор: p0s0l 31.8.2003, 16:19
Ну можно и is использовать, правда is проверяет, является ли object классом TMyObjectClass или наследником этого класса. Поэтому если класс известен, то лучше использовать равенство, если не известен, то is класс, от которого наследуются классы объектов, которые ты проверяешь, в крайнем случае, TObject.
Код
function CheckObject(ob : TObject; AClass : TClass) : boolean;
begin
 Result := false;
 if IsBadReadPtr(pointer(ob), 4) then exit; // можно ли читать эту память
 if ob.ClassType = AClass then Result := true; // можно так
//  if ob is AClass then Result := true; // можно и так
end;

вызов: if not CheckObject(YourObject, TObject) then // неинициализирован

Автор: p0s0l 31.8.2003, 16:38
Вместо 4 лучше юзать AClass.InstanceSize.
А is вообще не работает, т.к. если объект указывает на какую-нибудь чушь, то is пытается отследить предков класса этого объекта, а класс объекта вообще не существует (т.к. объект указывает на мусор, а первые 4 байта, как я уже говорил - это указатель на класс)...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)