A bold guess for the Object Pascal compiler to assign a stack of memory details (below)
9CBS roast chicken wings
I have read the netizens of my previous article, I know that I am a guy who likes "the root of the roots", "dead drill angle". Recently, since the work needs to be transferred to Delphi, after exposure to Object Pascal, it really appreciates its neat and beautiful, and the author of "programming language: design and realization" is also praised by Pascal is "a very beautiful language". However, there have been many problems in the learning process, especially those who learn from C to OP [Object Pascal, because I have different languages, and the question mark will be more. Among them, a big difference in the OP and C languages is: the memory allocation mechanism of the class object [or known as the class instance] is different. Two of them have to say:
First, when is it allocated?
In C , the object is defined, then the memory is allocated, then the constructor is called, this memory may be in the stack, or may be in the full data area. But OP is very different, defines an object, such as: Obj: TOBJECT; just assigns 4 bytes of a pointer space, and the real object space has not been assigned, how is it used? Of course, it is necessary to assign space to the object before use, or it will cause access to memory errors, and it is also simple to assign space to objects:
Obj: = TOBJECT.CREATE;
OK, this object space is allocated in the heap, you know that in the stack is automatically recycled after the use period, but the pluck memory needs the programmer to manage itself, so after using the class object, don't forget obj.free [True implementation is Obj.Destroy, but Obj.Free is a safer way].
"When to assign" this problem is indeed different on the answer on OP and C , but it is not "doubts". I know that the OP class object is to get such a statement (constructor): obj: = TOBJECT.CREATE; how to get a stack of memory, how is the compiler to allocate a stack memory inside?
Please see the next question:
Second, how does the OP compiler allocated?
First of all, I would like to thank Lippman's "Inside C Ojbect Model". This is a non-much good book. She told you some of you most confused for C compiler, but also the details of the most, but I don't know the Delphi industry. Is there such a book, you can make me clearly understand how the OP compiler is specific [specific to each detail] how to assign a stack memory for a class object [If there is such a book, you must notify me: CODER @ Vip.sina.com]?
I boldly guess!
Some small actions are already defined in advance within the TOBJECT class! Let's pay attention to these Tobject class methods (TOBJECT is defined in system.pas):
TOBJECT = Class
......
Constructor crete;
PROCEDURE FREE
Class Function InitInstance (Instance: Pointer): TOBJECT;
Procedure Cleanupinstance;
Class Function InstanceSize: longint;
Class function newinstance: TOBJECT; Virtual
DESTRUCTOR DESTROY; Virtual;
END;
From the name of the method, we can faint feelings: NewInstance and FreeInstance are sure and descriptions of the structure and destructors of the class!
First analyze newinstance:
Class Function TOBJECT.NEWINSTANCE: TOBJECT
Begin
Result: = INITINSTANCE (_getMem (instancesize));
END;
There is only one code, but three other methods are called:
1,
Class Function TOBJECT.INSTANCESIZE: Longint
Begin
Result: = Pinteger (Integer VmtinstanceSize) ^
END;
This method is an important way to implement RTTI, which can return to the size of the stack memory. Note that it is not the size of the class object, because the class object is a pointer, then in the 32-bit environment, The pointer is always 4 bytes!
Everyone may be confused about this code: = Pinteger (Integer (Self) VmtinstanceSize) ^; I define a OP class:
TBASE = Class (TOBJECT)
x: integer;
Y: Double;
Constructor crete;
END;
Then allocate memory:
B: TBASE;
B: = TBASE.CREATE;
I envisage the distributed memory layout should be such a [Memory to consider the memory of the C object]:
Look at this sentence: Result: = Pinteger (Integer (Self) VmtinstanceSize) ^; its purpose is to take the content in the VMT index = -40 [Note: Constant VMTINSTANCESIZE = -40]. Everyone sees here
What is the value of the SELF variable? Is B's value is also VPTR's address? Absolutely not! Because the program is executing how many stacks are required to be divided by calling it, it is not officially assigned a stack memory, that is, VPTR, X, Y does not exist [but VMT is established together with the class. It contains some information related to the class. If the class instance needs to request the size of the memory, the size of the memory, etc.], of course, this self cannot be b value, I guess its content is INDEX = 0 Terries' address, only this, the code here, the code you want can be explained normally, but how is SELF being assigned to this value, I want to be the process made by the compiler.
In this way, Result: = Pinteger (Integer (Self) VMTINSTANCESIZE) ^ Nature Get information on the number of memory size!
In order to prove that my guess is correct, everyone can experiment with the following code:
VAR
B: TBASE;
SIZE_B: Integer;
Begin
B: = TBASE.CREATE;
ShowMessage (Format ('INITANCESIZE OF TBASE:% D', [B.InstanceSize]);
SIZE_B: = Pinteger (pinteger (b) ^ - 40) ^;
ShowMessage (Format ('INITANCESIZE OF TBASE:% D', [SIZE_B])); ......
END;
Everyone can see that the two methods get the same value!
Ok, now we go back to explain the second function to be called in Tobject.newInstance.
2, function _getmem (size: integer): Pointer;
It is defined in System.PAS as follows:
Function _getmem (size: integer): Pointer;
{$ If defined (debug) and defined (linux)}
VAR
Signature: Plongint;
{$ Ifend}
Begin
IF size> 0 THEN
Begin
{$ If defined (debug) and defined (linux)}
Signature: = Plongint (MemoryManager.getMem (Size 4));
if Signature = NIL THEN
Error (ReutofMemory);
SIGNATURE ^: = 0;
Result: = POINTER (Longint (Signature) 4);
{$ Else}
Result: = MemoryManager.getMem (size);
if Result = nil dam
Error (ReutofMemory);
{$ Ifend}
end
Else
Result: = NIL;
END;
The specific code is not analyzed, but we finally saw the specific function of allocating the memory in the OP, which is OP is the heap memory space acquired by a memory manager MemoryManager!
The third call in TOBJECT.NEWINSTANCE:
3,
Class Function TOBJECT.INITINSTANCE (Instance: Pointer): TOBJECT
{IFDEF PurePascal}
VAR
INTFTABLE: PINTERFACETABLE;
Classptr: TCLASS;
I: integer;
Begin
Fillchar (Instance ^, InstanceSize, 0);
Pinteger (Instance) ^: = Integer (Self);
Classptr: = Self;
While Classptruth <> NIL DO
Begin
INTFTABLE: = Classptr.getInterfaceTable;
IF INTFTABLE <> NIL THEN
For i: = 0 to intftable.Entrycount-1 DO
With intftable.entries [i] do
Begin
IF vTable <> nil dam
Pinteger (@pchar (instance) [ioffset]) ^: = integer (vTable);
END;
Classptr: = Classptr.classParent;
END;
RESULT: = Instance;
END;
{$ Else}
ASM
Push EBX
PUSH ESI
Push EDI
MOV EBX, EAX
MOV EDI, EDX
Stosd
MOV ECX, [EBX] .VmtinstanceSize
XOR EAX, EAX
Push ECX
SHR ECX, 2
Dec ECX
Rep StosDPOP ECX
And ECX, 3
Rep Stosb
MOV EAX, EDX
MOV EDX, ESP
@@ 0: MOV ECX, [EBX] .VmtintFTable
Test ECX, ECX
JE @@ 1
Push ECX
@@ 1: MOV EBX, [EBX] .vmtparent
Test EBX, EBX
JE @@ 2
MOV EBX, [EBX]
JMP @@ 0
@@ 2: CMP ESP, EDX
JE @@ 5
@@ 3: POP EBX
MOV ECX, [EBX] .tinterfaceTable.Entrycount
Add ebx, 4
@@ 4: MOV ESI, [EBX] .tinterfaceentry.vtable
Test ESI, ESI
JE @@ 4a
Mov Edi, [EBX] .tinterfaceentry.ioffset
MOV [EAX EDI], ESI
@@ 4a: Add Ebx, Type TinterfaceEntry
Dec ECX
JNE @@ 4
CMP ESP, EDX
JNE @@ 3
@@ 5: POP EDI
POP ESI
POP EBX
END;
{$ ENDIF}
Just known that _getmem has got a stack memory space, and this method we have to discuss now is to initialize some must. Other codes regardless of this:
Fillchar (Instance ^, InstanceSize, 0);
Pinteger (Instance) ^: = Integer (Self);
The first is to give the class object clear, now we know why the field of the OP class instance will automatically initialize zero [String is empty, the pointer is nil]!
The second statement is to let the VTPR pointer point to the VMT table 0: Reader Please refer to the structure of the structural map, which also proves the correctness of the speculation of the SELF value].
(Endlessly)