Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2011-10

How are Assigned, Free, Nil and Destroy related?

18 messages · 11 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Frank Church

This is one question I have wanted to ask for a long time.

How are Assigned, Free, Nil and Destroy related, and when is one or another appropriate? What other procedure have I missed?

There are so many articles and mailing list threads on this issue that I don't think asking it makes me sound like a newbie, or does it?

Frank Church ======================= http://devblog.brahmancreations.com
Frank Church
to Frank Church
Frank Church wrote 15 lines
This is one question I have wanted to ask for a long time. How are Assigned, Free, Nil and Destroy related, and when is one or another appropriate? What other procedure have I missed? There are so many articles and mailing list threads on this issue that I don't think asking it makes me sound like a newbie, or does it? -- Frank Church ======================= http://devblog.brahmancreations.com

Is this too simple to warrant an answer? Should I take it to the forums?

Frank Church ======================= http://devblog.brahmancreations.com
Felipe Monteiro de Carvalho
to Frank Church: This is one question I have wanted to ask for a long time. How are Assigned, Free, Nil…

I understand Assigned as being the same as nil, so Assigned(Object) = Object nil

I vaguely remember that it could be safer in some corner case, but I don't remember ever meting that.

Free is how you release the memory allocated for a object. Free calls Destroy. Never call Destroy manually. When you implement the destructor you always implement Destroy, never change Free.

Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero.

The typical life-cycle of a object is:

MyObject := TMyObject.Create;
try
  MyObject.DoSomething();
finally
  MyObject.Free;
end;

To implement this object you should implement Create, DoSomething and Destroy.

Felipe Monteiro de Carvalho
Alexander Shishkin
to Felipe Monteiro de Carvalho

22.10.2011 10:20, Felipe Monteiro de Carvalho пишет:

Show quoted text 6 lines
I understand Assigned as being the same as nil, so Assigned(Object) = Object nil I vaguely remember that it could be safer in some corner case, but I don't remember ever meting that.

Method pointers?

Frank Church
to Felipe Monteiro de Carvalho: I understand Assigned as being the same as nil, so Assigned(Object) = Object nil I…

On 22 October 2011 07:20, Felipe Monteiro de Carvalho <

Show quoted text 34 lines
wrote: I understand Assigned as being the same as nil, so Assigned(Object) = Object nil I vaguely remember that it could be safer in some corner case, but I don't remember ever meting that. Free is how you release the memory allocated for a object. Free calls Destroy. Never call Destroy manually. When you implement the destructor you always implement Destroy, never change Free. Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero. The typical life-cycle of a object is: MyObject := TMyObject.Create; try MyObject.DoSomething(); finally MyObject.Free; end; To implement this object you should implement Create, DoSomething and Destroy. -- Felipe Monteiro de Carvalho _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

This code is the source of my woes. SCStrings and FBreakStrings are part of an object. They are repeatedly used in a loop and I need to free the memory after the loop runs or free the space taken up by their strings

type
Show quoted text 14 lines
TRuntimeMonitor = class(TThread) private Frequency: Integer; IniFile: TMemIniFile; SCStrings: TStringList; FBreakStrings: TStringList; procedure DispatchOutput; procedure DisplayRawOutput; protected procedure Execute; override; public constructor Create(CreateSuspended: Boolean); end;
* * procedure InitVars;
Show quoted text 22 lines
begin if not Assigned(SCStrings) then SCStrings := TStringList.Create; if not Assigned(FBreakStrings) then FBreakStrings := TStringList.Create; IniFile := TMemIniFile.Create('zxtyu'); end; procedure FreeVars; begin IniFile.Free; if Assigned(SCStrings) then SCStrings.Free; if Assigned(FBreakStrings) then FBreakStrings.Free; if Assigned(FBreakStrings) then debugln('FBreakStrings is still assigned'); end;

*

*InitVars and FreeVars run in the Execute procedure of the thread*

*When the loop runs again Assigned in InitVars is false so as soon as those FBreakStrings and SCStrings are accessed within the loop a SIGSEGV occurs. So what I want to know is whether Assigned remains true when Free is executed.

In the mean time instead of using Free in FreeVars I will set the text property to the blank string to release the memory used by the strings.

Frank Church ======================= http://devblog.brahmancreations.com
Ludo Brands
to Felipe Monteiro de Carvalho: I understand Assigned as being the same as nil, so Assigned(Object) = Object nil I…
Show quoted text 13 lines
Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero. The typical life-cycle of a object is: MyObject := TMyObject.Create; try MyObject.DoSomething(); finally MyObject.Free; end;

One pitfall: the variable MyObject before MyObject := TMyObject.Create; is undefined and not necessarily nil. Variables are not initialized by default and can contain anything. In general, MyObject.Free does not set MyObject to nil neither. Good practice is to initialize pointer variables to nil and resetting them to nil after freeing them whenever assigned() or nil is going to be used.

Ludo

Mattias Gaertner
to Alexander Shishkin: 22.10.2011 10:20, Felipe Monteiro de Carvalho пишет: Method pointers?

Alexander Shishkin hat am 22. Oktober 2011 um 08:31 geschrieben:

Show quoted text 8 lines
22.10.2011 10:20, Felipe Monteiro de Carvalho пишет: > I understand Assigned as being the same as  nil, so Assigned(Object) > = Object  nil > > I vaguely remember that it could be safer in some corner case, but I > don't remember ever meting that. > Method pointers? 

In former versions there was a difference for method pointers. Now it is the same. I'm not sure since when. 
 
 
Mattias
 

Ludo Brands
to Frank Church: On 22 October 2011 07:20, Felipe Monteiro de Carvalho < This code is the source of my…

When the loop runs again Assigned in InitVars is false so as soon as those FBreakStrings and SCStrings are accessed within the loop a SIGSEGV occurs. So what I want to know is whether Assigned remains true when Free is executed.

See my previous answer.

There is a helper function "procedure FreeAndNil(var obj);" that calls
obj.free and sets obj to nil. So instead of SCStrings.Free; SCStrings:=nil;
call FreeAndNil(SCStrings);

Ludo

Frank Church
to Ludo Brands: One pitfall: the variable MyObject before MyObject := TMyObject.Create; is undefined and…
Ludo Brands wrote 23 lines
> Nil is not a routine, it is a value, it means that the object > is empty, it does not exist / is not allocated. Nil in > existing implementations that I know is represented by the value zero. > > The typical life-cycle of a object is: > > MyObject := TMyObject.Create; > try > MyObject.DoSomething(); > finally > MyObject.Free; > end; > One pitfall: the variable MyObject before MyObject := TMyObject.Create; is undefined and not necessarily nil. Variables are not initialized by default and can contain anything. In general, MyObject.Free does not set MyObject to nil neither. Good practice is to initialize pointer variables to nil and resetting them to nil after freeing them whenever assigned() or nil is going to be used.

Does that mean that Free itself reclaims the memory used by the object's fields and properties but does not release the memory used by the TObject or pointer itself, where as setting it to nil or executing Destroy does, or does Destroy do something different?

Ludo

Show quoted text 5 lines
_______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Frank Church ======================= http://devblog.brahmancreations.com
Felipe Monteiro de Carvalho
to Frank Church
Frank Church wrote
Does that mean that Free itself reclaims the memory used by the object's fields and properties but does not release the memory used by the TObject or pointer itself, where as setting it to nil or executing Destroy does, or does Destroy do something different?

No, you got parts of it wrong:

*Free calls Destroy which releases the memory of the object itself.

*Nothing releases the memory of the pointer to the object. You don't want to release the 4 or 8 bytes of the pointer. If you did release it, then your application would crash when trying to read the pointer to check if it is nil.

*Destroy implements releasing the memory of the object. Free calls Destroy.

*Setting the object to nil does just that. It changes the pointer to the object to have the value nil (zero). It does not release the pointer.

Felipe Monteiro de Carvalho
Ludo Brands
to Frank Church: Does that mean that Free itself reclaims the memory used by the object's fields and…

Does that mean that Free itself reclaims the memory used by the object's fields and properties but does not release the memory used by the TObject or pointer itself, where as setting it to nil or executing Destroy does, or does Destroy do something different?

All memory is released including TObject but the variable pointing to the TObject (fe: SCStrings) isn't set to nil. It still points to where the TObject was. Warning: setting a TObject variable to nil does not free the object unless it is reference counted! Strings and COM style interfaces are reference counted. Pascal is not VB.

Ludo

Michael Müller
to Frank Church: On 22 October 2011 07:20, Felipe Monteiro de Carvalho < This code is the source of my…
Frank Church wrote 80 lines
On 22 October 2011 07:20, Felipe Monteiro de Carvalho wrote: I understand Assigned as being the same as nil, so Assigned(Object) = Object nil I vaguely remember that it could be safer in some corner case, but I don't remember ever meting that. Free is how you release the memory allocated for a object. Free calls Destroy. Never call Destroy manually. When you implement the destructor you always implement Destroy, never change Free. Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero. The typical life-cycle of a object is: MyObject := TMyObject.Create; try MyObject.DoSomething(); finally MyObject.Free; end; To implement this object you should implement Create, DoSomething and Destroy. -- Felipe Monteiro de Carvalho _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal This code is the source of my woes. SCStrings and FBreakStrings are part of an object. They are repeatedly used in a loop and I need to free the memory after the loop runs or free the space taken up by their strings type TRuntimeMonitor = class(TThread) private Frequency: Integer; IniFile: TMemIniFile; SCStrings: TStringList; FBreakStrings: TStringList; procedure DispatchOutput; procedure DisplayRawOutput; protected procedure Execute; override; public constructor Create(CreateSuspended: Boolean); end; procedure InitVars; begin if not Assigned(SCStrings) then SCStrings := TStringList.Create; if not Assigned(FBreakStrings) then FBreakStrings := TStringList.Create; IniFile := TMemIniFile.Create('zxtyu'); end; procedure FreeVars; begin IniFile.Free; if Assigned(SCStrings) then SCStrings.Free; if Assigned(FBreakStrings) then FBreakStrings.Free; if Assigned(FBreakStrings) then debugln('FBreakStrings is still assigned'); end; InitVars and FreeVars run in the Execute procedure of the thread When the loop runs again Assigned in InitVars is false so as soon as those FBreakStrings and SCStrings are accessed within the loop a SIGSEGV occurs. So what I want to know is whether Assigned remains true when Free is executed. In the mean time instead of using Free in FreeVars I will set the text property to the blank string to release the memory used by the strings.

In TRuntimeMonitor.Create() you should add

SCStrings := nil;
FBreakStrings := nil;

and in FreeVars() you should replace

    if Assigned(SCStrings) then
      SCStrings.Free;
    if Assigned(FBreakStrings) then
      FBreakStrings.Free;

by

FreeAndNil(SCStrings);
FreeAndNil(FBreakStrings);

You should also add a Destroy() with the FreeAndNil() lines to ensure that everything will be destroyed when freeing TRuntimeMonitor even if FreeVars() were not called or didn't finish 100% for what ever reason.

FreeAndNil() is one important function that was missing in your list. ;-)
FreeAndNil(Object) does
if Assigned(Object) then begin
  Object.Free;
  Object := nil;
end;

For locale objects Felipes example should be used.

Regards

Michael

Unknown author
to Frank Church: On 22 October 2011 07:20, Felipe Monteiro de Carvalho < This code is the source of my…

Hello,
Instead of .Free in your FreeVars routine, you should use FreeAndNil( theobject).

The correct lifecycle for class objects is :
var
  anObject : TMyObject;
begin
  anObject := nil; //not needed for class attributes. Required for local function or global unit variables.
  anObject := TMyObject.Create( params) //if an exception is raised here, the anObject reference will still be nill.
  try
    //... do some code on anObject...
  finally
    FreeAndNil( anObject); //after this, the memory referenced by anObject is freed, and the reference anObject is set to nil.
  end;
end;

Hope this helps,
Thierry

----- Mail Original -----
De: "Frank Church"
À: "FPC-Pascal users discussions"
Envoyé: Samedi 22 Octobre 2011 09h08:17 GMT +01:00 Amsterdam / Berlin / Berne / Rome / Stockholm / Vienne Objet: Re: [fpc-pascal] How are Assigned, Free, Nil and Destroy related?

On 22 October 2011 07:20, Felipe Monteiro de Carvalho < > wrote:

I understand Assigned as being the same as nil, so Assigned(Object) = Object nil

I vaguely remember that it could be safer in some corner case, but I don't remember ever meting that.

Free is how you release the memory allocated for a object. Free calls Destroy. Never call Destroy manually. When you implement the destructor you always implement Destroy, never change Free.

Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero.

The typical life-cycle of a object is:

MyObject := TMyObject.Create;
try
MyObject.DoSomething();
finally
MyObject.Free;
end;

To implement this object you should implement Create, DoSomething and Destroy.

Felipe Monteiro de Carvalho
Mark Morgan Lloyd
to Felipe Monteiro de Carvalho: I understand Assigned as being the same as nil, so Assigned(Object) = Object nil I…
Felipe Monteiro de Carvalho wrote
Free is how you release the memory allocated for a object. Free calls Destroy. Never call Destroy manually. When you implement the destructor you always implement Destroy, never change Free.

A number of years ago, Matthew Jones's wife looked over his shoulder and caught him using Create and Destroy. "Bit violent, isn't it?" When he told the story somebody else pointed out that he should be using Create and Free, I find this anecdote makes it easy to remember.

Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero.

I've once seen a compiler using a non-zero value, I think it was the first Logitech protected-mode Modula-2 and it used ffff:0000. Apart from that I think that C specifies that nil has a bit pattern of all zeros, and anything with even the slightest interest in compatibility sticks to this as a convention.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]
Marco van de Voort
to Felipe Monteiro de Carvalho: I understand Assigned as being the same as nil, so Assigned(Object) = Object nil I…

In our previous episode, Felipe Monteiro de Carvalho said:

Nil is not a routine, it is a value, it means that the object is empty, it does not exist / is not allocated. Nil in existing implementations that I know is represented by the value zero.

Look better in, euh, Free Pascal, and see what is assigned in this case:-)

type txxxx = procedure (a,b:integer) of object;
var x : txxxx;
begin
  x:=nil;
end.

nil is not always zero. Sometimes it is double zero :-)

Frank Peelo
to Mark Morgan Lloyd: A number of years ago, Matthew Jones's wife looked over his shoulder and caught him using…
Mark Morgan Lloyd wrote 21 lines
Felipe Monteiro de Carvalho wrote: > Free is how you release the memory allocated for a object. Free calls > Destroy. Never call Destroy manually. When you implement the > destructor you always implement Destroy, never change Free. A number of years ago, Matthew Jones's wife looked over his shoulder and caught him using Create and Destroy. "Bit violent, isn't it?" When he told the story somebody else pointed out that he should be using Create and Free, I find this anecdote makes it easy to remember. > Nil is not a routine, it is a value, it means that the object is > empty, it does not exist / is not allocated. Nil in existing > implementations that I know is represented by the value zero. I've once seen a compiler using a non-zero value, I think it was the first Logitech protected-mode Modula-2 and it used ffff:0000. Apart from that I think that C specifies that nil has a bit pattern of all zeros, and anything with even the slightest interest in compatibility sticks to this as a convention.

Almost -- In C, NULL doesn't have to be all zeroes internally, but the value 0 in the source code represents the NULL pointer. The compiler is allowed to convert (void*)0 to a different bit pattern if the hardware requires it, but you'd need a pretty good reason to make life that complicated. So it would be a rare compiler that did that.

If I recall corerctly, that Modula-2 value for nil was the address the 8086 jumped to when released from RESET. So jumping through a pointer with value nil would be something you would notice pretty much immediately.

FP

Ralf A. Quint
to Frank Peelo
Frank Peelo wrote
If I recall corerctly, that Modula-2 value for nil was the address the 8086 jumped to when released from RESET. So jumping through a pointer with value nil would be something you would notice pretty much immediately.

Certainly not. Modula-2 was/is not depending on any CPU specifics, certainly not on anything x86, considering that the first computers Modula-2 ran on were the Xerox Alto and the Lilith, using M-Code, and both not even a remote connection to anything x86. And a lot of non-Wirth Modula-2 implementation ran on Motorola 68k before I can remember to have seen the first x86 implementation (not sure if it was FST or XDS)...

Ralf

Mark Morgan Lloyd
to Ralf A. Quint
Ralf A. Quint wrote 14 lines
At 11:52 AM 10/23/2011, Frank Peelo wrote: > If I recall corerctly, that Modula-2 value for nil was the address the > 8086 jumped to when released from RESET. So jumping through a pointer > with value nil would be something you would notice pretty much > immediately. Certainly not. Modula-2 was/is not depending on any CPU specifics, certainly not on anything x86, considering that the first computers Modula-2 ran on were the Xerox Alto and the Lilith, using M-Code, and both not even a remote connection to anything x86. And a lot of non-Wirth Modula-2 implementation ran on Motorola 68k before I can remember to have seen the first x86 implementation (not sure if it was FST or XDS)...

We're getting off-topic. I *DID* specify that it was one, particular compiler that had that behaviour: if I recall correctly it was the first version that Logitech targeted at OS/2 (the one that bombed when you said BYTE(0)). I've also seen ffff:0000 used by a disassembler (Sourcer), possibly for the same value that Frank suggests.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]