The detailed analysis of the destructional order of parameter objects and local objects in c++ is analyzed
- 2020-04-01 23:33:10
- OfStack
The following is the source of c++ :
class X {
public:
int i;
int j;
~X() {}
};
void f(X x) {
X x1;
x.i = 1;
x.j = 2;
}
int main() {
f(X());
}
The following is the assembly code of the main function:
_main PROC
; 15 : int main() {
push ebp
mov ebp, esp
sub esp, 8; Reserved for temporary objects 8byte Space, since the definition constructor is not shown,
; And in this case the compiler provides a useless default constructor, so the constructor call is not seen
; 16 : f(X());
mov eax, DWORD PTR $T2560[ebp+4]; The first address of the temporary variable is offset 4byte The contents in memory are given eax , the member variable that is about to be a temporary variable j Values for eax
push eax; will eax The pressure of stack
mov ecx, DWORD PTR $T2560[ebp]; Gives the contents of the first address of the temporary variable ecx , is a member variable in a temporary variable i Values for ecx
push ecx; will ecx The pressure of stack
; The above four sentences create a copy of the temporary variable, called as a parameter f
call ?f@@YAXVX@@@Z ; Call a function f
add esp, 8; Move the top of the stack pointer down 8byte , freeing the stack space provided for the parameter object
lea ecx, DWORD PTR $T2560[ebp]; Gives the first address of the temporary object ecx
call ??1X@@QAE@XZ ; A destructor is called for a temporary object
; 17 : }
xor eax, eax
mov esp, ebp
pop ebp
ret 0
_main ENDP
As you can see above, the resulting temporary object does not call the destructor until the function call exits.
The following is the assembly code of f function:
?f@@YAXVX@@@Z PROC ; f
; 9 : void f(X x) {
push ebp
mov ebp, esp
sub esp, 8; Is a local object x1 The reserved 8byte The space of
; 10 : X x1;
; 11 : x.i = 1;
mov DWORD PTR _x$[ebp], 1; the 1 Write to the first address of the parameter object 1 Writes a member variable to the parameter object i
; 12 : x.j = 2;
mov DWORD PTR _x$[ebp+4], 2; the 2 Writes the first address of the offset parameter object 4byte In memory, that is to put 2 Writes a member variable to the parameter object j
; 13 :
; 14 : }
lea ecx, DWORD PTR _x1$[ebp]; Local variables x1 The first address of ecx
call ??1X@@QAE@XZ ; for x1 Call the destructor
lea ecx, DWORD PTR _x$[ebp]; Gives the first address of the parameter object to ecx
call ??1X@@QAE@XZ ; The destructor is called for the argument object
mov esp, ebp
pop ebp
ret 0
?f@@YAXVX@@@Z ENDP ; f
; Function compile flags: /Odtp
_TEXT ENDS
; COMDAT ??1X@@QAE@XZ
_TEXT SEGMENT
_this$ = -4 ; size = 4
??1X@@QAE@XZ PROC ; X::~X, COMDAT
; _this$ = ecx
; 6 : ~X() {}
push ebp
mov ebp, esp
push ecx
mov DWORD PTR _this$[ebp], ecx
mov esp, ebp
pop ebp
ret 0
??1X@@QAE@XZ ENDP
As you can see from the above code, both the argument object and the local object call the destructor before the function exits. And the argument object calls its own destructor after the destructor is called by the local object.