在另一个静态对象的析构函数内构造的静态对象的析构函数
我有一些析构函数的问题,在下面的代码:
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");
}
为什么析构函数foo2没有调用 bionic
并且用于 glibc
?
Why destructor for foo2 wasn't called for bionic
and was for glibc
?
EDIT
bionic的输出:
EDIT
Output for bionic:
main 1
foo1 const
main 2
foo1 dest
foo2 const
return foo2
调试信息:
(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]
我认为你的代码有未定义的行为,虽然标准
不是很清楚在
标准中找不到它)。你的代码在静态对象的
析构函数中构造一个新的静态对象。该标准不处理
这种情况,但是:
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:
-
它说的析构函数必须在反向
施工顺序。在你的情况下,这意味着GetFoo2
中的
静态对象必须在
构造之前被销毁,这是自相矛盾的。
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.
§3.6/ 3中的文本描述了析构函数的顺序
和注册到 atexit
。要求是
,这样每个都必须使用相同的注册机制。
一旦你调用 exit
(或从
返回),调用 atexit
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.6/ 2,它说如果一个函数包含
a静态或线程存储持续时间的块范围对象
已被销毁,并且在
销毁静态或线程存储
持续时间的对象时调用该函数,程序具有未定义的行为,如果
控制的流通过先前的
销毁的blockscope对象的定义。这句话说的是
被毁坏的对象,但是它没有太多的想象力认为
,没有构造对象的缺漏只是一个
监督。
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.
最后,我会说我的第一点是结论
关于意向。在§1.3.24中,有一个注释(非规范,
,但表示意图)当本国际标准没有明确定义
行为时,程序使用错误的构造或
错误的数据。在这种情况下,
需要的行为的唯一描述是不可能的(因为你不能在构造之前破坏
对象),标准没有说明如何解决这个问题。
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.