在具有静态对象的类的析构函数中使用exit()不会像预期的那样结束于无限循环中 [英] Using exit() in destructor of a class having static object, doesn't end up in an infinite loop as expected
问题描述
我在第10章,Bruce Eckel的C ++第1卷中讨论过这个问题。
I came across this in chapter 10, Thinking in C++ vol.1 by Bruce Eckel.
静态对象的析构函数,所有具有静态存储的对象,而不仅仅是上面示例中的局部静态对象)在main()退出时或者当显式调用标准C库函数exit()时被调用。在大多数实现中,main()在终止时调用exit()。这意味着在析构函数中调用exit()可能很危险,因为你可能会遇到无限递归。
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
我的编译器足够聪明吗?我在Ubuntu上使用GCC 4.7.2。
Is my compiler smart enough to handle this? I am using GCC 4.7.2 on Ubuntu.
推荐答案
我确定这是在未定义的行为 。我不能在C ++标准中找到一个段落,但很明显,如果你调用 exit()
从发生的事情,因为你调用 exit()
,你很可能会陷入无限循环。这是不能保证的,因为全局析构函数的处理可以通过首先从一些列表[1]中删除它,然后调用析构函数来处理要销毁的事物列表。因此,如果 exit
被再次调用,它将处于已经处理该对象的状态。
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".
标准当然不会说你必须应付 exit()
被多次调用 - 很可能另一个C ++库将无法应对这种情况。
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.
并且是迂腐的:它不是那么多的编译器作为C ++或经典的C运行时库处理这个。
And being pedantic: It's not so much the compiler as the C++ or classic C runtime library that deals with this.
[1]通过列表,我不是说 std :: list
,而是一个通用的Some一种容纳需要销毁的容器。
[1] By list, I'm not saying std::list
, but a generic "Some sort of container holding what needs to be destroyed".
这篇关于在具有静态对象的类的析构函数中使用exit()不会像预期的那样结束于无限循环中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!