Using exit() in destructor of a class having stati

2019-09-09 04:37发布

I came across this in chapter 10, Thinking in C++ vol.1 by Bruce Eckel.

Destructors for static objects (that is, all objects with static storage, not just local static objects as in the example above) are called when main( ) exits or when the Standard C library function exit( ) is explicitly called. In most implementations, main( ) just calls exit( ) when it terminates. This means that it can be dangerous to call exit( ) inside a destructor because you can end up with infinite recursion

I also came across this question in SO. Then, I wrote a code myself to simulate this recursion but I failed. Here's how my code looks like.

#include <iostream>
#include <cstdlib>

class Test
{
    private:
        std::string _name;
        static Test obj1;
        static Test obj2;
    public:
        Test(std::string name)
        {
            std::cout << "in constructor:" << name << std::endl;
            _name = name;
        }
        ~Test()
        {
            std::cout << "in destructor:" << _name << std::endl;
            if ("class static 2" == _name)
            {
                std::cout << "calling exit" << std::endl;
                exit(2);
                std::cout << "should not print this" << std::endl;
            }
        }
};

Test global("global");
Test Test::obj1("class static 1");
Test Test::obj2("class static 2");

int main(void)
{
    static Test mainStatic_1("main static");

    return 0;
}

And this is the output I got, without any infinite looping

in constructor:global
in constructor:class static 1
in constructor:class static 2
in constructor:main static
in destructor:main static
in destructor:class static 2
calling exit
in destructor:class static 1
in destructor:global

Is my compiler smart enough to handle this? I am using GCC 4.7.2 on Ubuntu.

2条回答
萌系小妹纸
2楼-- · 2019-09-09 04:50

I'm pretty sure this comes under the heading of "undefined behaviour". I can't find a paragraph in the C++ standard to say so, but it's pretty obvious that if you call exit() from something that happened because you called exit(), chances are that you end up in an infinite loop. It is not guaranteed, because the handling of the global destructors may be done in such a way that the list of things to destroy is dealt with by first removing it from some the list [1], then calling the destructor. So if exit is called again, it will be in a state where it "has already dealt with this object".

The standard certainly doesn't say "You must cope with exit() being called multiple times - so it's quite possible that another C++ library will fail to cope with this.

And being pedantic: It's not so much the compiler as the C++ or classic C runtime library that deals with this.

[1] By list, I'm not saying std::list, but a generic "Some sort of container holding what needs to be destroyed".

查看更多
太酷不给撩
3楼-- · 2019-09-09 05:04

Is my compiler smart enough to handle this?

It would appear that they have added some safeguards for it, but it is still a bad practice nonetheless.

查看更多
登录 后发表回答