Can a destructor be recursive?

后端 未结 5 759
北荒
北荒 2021-02-01 00:55

Is this program well-defined, and if not, why exactly?

#include 
#include 
struct X {
    int cnt;
    X (int i) : cnt(i) {}
    ~X()          


        
5条回答
  •  时光说笑
    2021-02-01 01:39

    Okay, we understood that behavior is not defined. But let's do small journey into what really happends. I use VS 2008.

    Here is my code:

    class Test
    {
    int i;
    
    public:
        Test() : i(3) { }
    
        ~Test()
        {
            if (!i)
                return;     
            printf("%d", i);
            i--;
            Test::~Test();
        }
    };
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        delete new Test();
        return 0;
    }
    

    Let's run it and set a breakpoint inside destructor and let the miracle of recursion happen.

    Here is stack trace:

    What is that scalar deleting destructor? It is something that compiler inserts between delete and our actual code. Destructor itself is just a method, there is nothing special about it. It doesn't really release the memory. It is released somewhere inside that scalar deleting destructor.

    Let's go to scalar deleting destructor and take a look at the disassembly:

    01341580  mov         dword ptr [ebp-8],ecx 
    01341583  mov         ecx,dword ptr [this] 
    01341586  call        Test::~Test (134105Fh) 
    0134158B  mov         eax,dword ptr [ebp+8] 
    0134158E  and         eax,1 
    01341591  je          Test::`scalar deleting destructor'+3Fh (134159Fh) 
    01341593  mov         eax,dword ptr [this] 
    01341596  push        eax  
    01341597  call        operator delete (1341096h) 
    0134159C  add         esp,4 
    

    while doing our recursion we are stuck at address 01341586, and memory is actually released only at address 01341597.

    Conclusion: In VS 2008, since destructor is just a method and all memory release code are injected into middle function (scalar deleting destructor) it is safe to call destructor recursively. But still it is not good idea, IMO.

    Edit: Ok, ok. The only idea of this answer was to take a look at what is going on when you call destructor recursively. But don't do it, it is not safe generally.

提交回复
热议问题