c – 在另一个静态对象的析构函数中构造的静态对象的析构函数

我在下一个代码中遇到了析构函数的一些问题:

#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的析构函数不是为了仿生而被称为glibc?

编辑
仿生输出:

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]
最佳答案
我认为你的代码有不确定的行为,虽然标准
对它不是很清楚(或者我找不到它
标准).你的代码构造了一个新的静态对象
静态对象的析构函数.该标准没有解决
这种情况,但是:

>它确实说必须反过来调用析构函数
施工顺序.在你的情况下,这将意味着
GetFoo2中的静态对象必须在它之前被破坏
建构,这是自相矛盾的.
>§3.6/ 3中的文字描述了析构函数的排序
和atexit注册的功能.要求是
这样每个人都必须使用相同的注册机制.
一旦你调用退出(或从.返回)调用atexit
main)是未定义的行为.
>还有§3.6/ 2,它说“如果一个函数包含
静态或线程存储持续时间的块范围对象
已被破坏,并在该期间调用该函数
使用静态或线程存储破坏对象
持续时间,程序具有未完成的行为,如果流动的
控制通过以前的定义
破坏了blockcope对象.“这句话谈到了alread
摧毁了物体,但思考并不需要太多想象力
缺乏“尚未构建”的对象只是一个
监督.

最后,我要说的是我上面的第一点是结论性的
关心意图.在§1.3.24中,有一个注释(非规范性,
但指示意图)“可能会预期未定义的行为
当本国际标准遗漏任何明确的定义时
行为或程序使用错误的结构或
错误的数据.“在这种情况下,唯一的描述
所需的行为是不可能的(因为你不能破坏一个
对象在构建之前),标准什么也没说
关于如何解决这个问题.

转载注明原文:c – 在另一个静态对象的析构函数中构造的静态对象的析构函数 - 代码日志