Using exit() in destructor of a class having static object, doesn't end up in an infinite loop as expected

陌路散爱 提交于 2019-12-11 23:43:41

问题


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.


回答1:


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".




回答2:


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.



来源:https://stackoverflow.com/questions/17627868/using-exit-in-destructor-of-a-class-having-static-object-doesnt-end-up-in-an

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!