Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destructor of a static object constructed within the destructor of another static object

I have some problems with destructor, in next code:

#include <stdlib.h>
#include <cstdio>

class Foo2
{
    public:
        Foo2() { printf("foo2 const\n"); }

        ~Foo2()
        {
            printf("foo2 dest\n"); //  <--- wasn't called for bionic libc
        }
};

static Foo2& GetFoo2()
{
    static Foo2 foo2;
    printf ("return foo2\n");
    return foo2;
}

class Foo1
{
    public:
        Foo1() { printf("foo1 const\n"); }

        ~Foo1()
        {
            printf("foo1 dest\n");
            GetFoo2();
        }
};

int main( int argc, const char* argv[] )
{
        printf("main 1 \n");
        static Foo1 anotherFoo;
        printf("main 2 \n");
}

Why destructor for foo2 wasn't called for bionic and was for glibc?

EDIT
Output for bionic:

main 1  
foo1 const  
main 2  
foo1 dest  
foo2 const  
return foo2  

Debug info:

(gdb) break 22
Breakpoint 1 at 0x8048858: file test.C, line 22.
(gdb) info breakpoints
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x08048858 in Foo2::~Foo2() at test.C:22
(gdb) cont
[    exited with code 0]
like image 208
Laser Avatar asked Jan 11 '13 12:01

Laser


People also ask

Can a destructor be static?

Static object destructors This means that it can be dangerous to call exit( ) inside a destructor because you can end up with infinite recursion. Static object destructors are not called if you exit the program using the Standard C library function abort( ).

What is destructor how destructor is declared when destructor is invoked?

A destructor is a member function that is invoked automatically when the object goes out of scope or is explicitly destroyed by a call to delete . A destructor has the same name as the class, preceded by a tilde ( ~ ). For example, the destructor for class String is declared: ~String() .

At which point does a destructor of a dynamically allocated class object get called?

A class' destructor is called whenever an object of the class goes out of scope.

How do you destroy static objects?

The static objects are only destroyed when the program terminates i.e. they live until program termination.


1 Answers

I think your code has undefined behavior, although the standard isn't really clear about it (or I can't find it in the standard). Your code constructs a new static object in the destructor of a static object. The standard doesn't address this case, but:

  1. It does say that destructors must be called in the reverse order of construction. In your case, this would imply that the static object in GetFoo2 must be destructed before it was constructed, which is self-contradictory.

  2. The text in §3.6/3 describes the sequencing of destructors and functions registered with atexit. The requirements are such that the same registration mechanism must be used for each. And calling atexit once you've called exit (or returned from main) is undefined behavior.

  3. There's also §3.6/2, which says that "If a function contains a block-scope object of static or thread storage duration that has been destroyed and the function is called during the destruction of an object with static or thread storage duration, the program has undefined behavior if the flow of control passes through the definition of the previously destroyed blockscope object." This sentence talks about alread destroyed objects, but it doesn't take much imagination to think that the absense of "not yet constructed" objects is just an oversight.

In the end, I'd say that my first point above is conclusive with regards to intent. In §1.3.24, there is a note (non normative, but indicative of intent) "Undefined behavior may be expected when this International Standard omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data." In this case, the only description of the required behavior is impossible (since you cannot destruct an object before it was constructed), and the standard says nothing about how this should be resolved.

like image 96
James Kanze Avatar answered Oct 06 '22 08:10

James Kanze