Professional Documents
Culture Documents
Practically every developer, even a newcomer in programming, can create and destroy objects
correctly. A classic construction that is used in the majority of programs looks the following way:
Delphi/Pascal
1 MyObject:= TMyClass.Create();
2 try
3 {some code…}
4 finally
5 MyObject.Free;
6 end;
Yet, some time ago, there were a lot of discussions where to place object creation: before an
exception handler or within the try-finally-end construction. Of course, now, it is not difficult to find
an answer to this question. An example of well-written code can be found on many online
resources, such as StackOverflow, in books and in official documentation.
But do you really understand why it is so and what can happen if you use the wrong variant? It is
possible that you will have to answer this question during a technical interview. If you do not know
the correct answer, just keep reading this article!
Delphi/Pascal
1 TMyClass = class
2 private
3 function getSelfPointer: Pointer;
4 public
5 constructor Create(beRaized: Boolean = False);
6 procedure Free; overload;
7 end;
8
9 implementation
10
11 {$R *.dfm}
12
13 { TMyClass }
14 constructor TMyClass.Create(beRaized: Boolean);
15 begin
16 if beRaized then
17 raise Exception.Create('Error Message');
18 end;
19
20 procedure TMyClass.Free;
21 begin
22 // inherited;
23 CodeSite.Send( 'Destroy object');
24 {$IFNDEF AUTOREFCOUNT}
25 if Self <> nil then
26 begin
27 CodeSite.Send( ' Destroyed object address:', IntToHex(Integer(Pointer(self))));
28 Destroy;
29 end;
30 {$ENDIF}
31 end;
32
33
34 function TMyClass.getSelfPointer: Pointer;
35 begin
36 Result := Pointer(Self);
37 end;
In our class we will redefine the Free method only for having a look at the address of the object that
we want to destroy. We will copy the code that will destroy the object from the Free method of the
TObject class. The only unique method will be getSelfPointer that returns the Pointer to the Object.
The class constructor as a parameter will have a logical meaning. If it equals True, an exception will
be generated and an object won’t be created.
Delphi/Pascal
1 var
2 fMain: TfMain;
3
4 MyObject,
5 MyObject2: TMyClass;
Delphi/Pascal
1 procedure TfMain.Button1Click(Sender: TObject);
2 begin
3 MyObject:= TMyClass.Create();
4 try
5 CodeSite.Send('Actual MyObject address: ', IntToHex(Integer(MyObject.getSelfPointer ), 8))
6 finally
7 MyObject.Free;
8 end;
9
10 MyObject2:= TMyClass.Create();
11 try
12 CodeSite.Send('MyObject2 was created. Actual MyObject2 address: ', IntToHex(Integer(MyObje
13 // MyObject:= TMyClass.Create(True);
14 try
15 CodeSite.Send('Try creating MyObject');
16
17 MyObject:= TMyClass.Create(True);
18
19 finally
20 CodeSite.Send( 'MyObject. Finally');
21 MyObject.Free;
22 end;
23 finally
24
25 end;
26 end;
27
28 procedure TfMain.Button2Click(Sender: TObject);
29 begin
30 CodeSite.Send( 'MyObject2.ClassName', MyObject2.ClassName );
31 end;
To begin with, we create an object MyObject and put its address in the memory to the log and
immediately destroy it. Then we create MyObject2, check its address in the log and then create
MyObject again. At the same time, we generate an exception in the constructor. Actually, this object
won’t be created.
Delphi/Pascal
1 Actual MyObject address: = 018A8B80
2 Destroy object
3 Destroyed object address: = 018A8B80
4 MyObject2 was created. Actual MyObject2 address: = 018A8B80
5 Try creating MyObject.
6 MyObject. Finally
7 Destroy object
At the very beginning, MyObject is created and then it is immediately destroyed. Then MyObject2 is
created. And here’s where we have the first surprise. The address of a new object is fully identical to
the address of the object that has been destroyed. But, actually, there is nothing unexpected given
the peculiarities of how the object storage is organized in Delphi.
Then we need to bear in mind that though the Free method destroys an object, it doesn’t destroy the
link that leads to it.
Delphi/Pascal
1 try
2 CodeSite.Send('Try creating MyObject');
3
4 MyObject:= TMyClass.Create(True);
5
6 finally
7 CodeSite.Send( 'MyObject. Finally');
8 MyObject.Free;
9 end;
We remember that the object won’t be created. But a static method Free will consider that the
object is still available at the address 018A8B80 as the link after the first creation of the object is
stored. But in reality that’s the address of another object which will be destroyed. To make sure that
it is so, it is enough just to press Button2.
Delphi/Pascal
1 procedure TfMain.Button2Click(Sender: TObject);
2 begin
3 CodeSite.Send( 'MyObject2.ClassName', MyObject2.ClassName );
4 end;
As a result, due to using this construction for creating and destroying an object, we have destroyed
another object. Similar errors are quite dangerous when it comes to lists of objects. And the search
for such errors is a rather challenging process. It is obvious that nothing of this kind happens if we
create MyObject for the second time in a way that is applied in the majority of cases.
Delphi/Pascal
1 MyObject:= TMyClass.Create(True);
2 try
3 CodeSite.Send('Try creating MyObject');
4
5 finally
6 CodeSite.Send( 'MyObject. Finally');
7 MyObject.Free;
8 end;
This article was written by an Embarcadero Tech Partner. For more articles by Softacom and our
other Tech Partners click the following link: https://blogs.embarcadero.com/category/tech-
partner/
Tags: code, delphi, delphi objects, developer, programming, rad studio, tech partner, techpartner
Leave a Comment
Embarcadero RAD Studio, Delphi, & C++Builder Blogs Back to top