8

在下一个代码中,我对析构函数有一些问题:

#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并且是 for 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]
4

4 回答 4

6

我认为您的代码具有未定义的行为,尽管标准并不清楚(或者我在标准中找不到它)。您的代码在静态对象的析构函数中构造了一个新的静态对象。该标准没有解决这种情况,但是:

  1. 它确实说必须以构造的相反顺序调用析构函数。在您的情况下,这意味着GetFoo2必须在构造静态对象之前对其进行破坏,这是自相矛盾的。

  2. §3.6/3 中的文本描述了使用atexit. 要求是必须为每个使用相同的注册机制。并且atexit一旦你调用exit(或从返回 main)调用是未定义的行为。

  3. 还有§3.6/2,它说“如果一个函数包含一个已被销毁的静态或线程存储持续时间的块范围对象,并且在销毁具有静态或线程存储持续时间的对象期间调用该函数,则程序如果控制流通过先前销毁的块范围对象的定义,则具有未定义的行为。” 这句话说的是已经销毁的对象,但不费吹灰之力就可以认为“尚未构建”对象的缺失只是一个疏忽。

最后,我想说我上面的第一点就意图而言是决定性的。在第 1.3.24 节中,有一条注释(非规范性,但表明意图)“当本国际标准省略任何明确的行为定义或程序使用错误的构造或错误数据时,可能会出现未定义的行为。” 在这种情况下,对所需行为的唯一描述是不可能的(因为您无法在构造对象之前对其进行破坏),并且该标准没有说明应如何解决此问题。

于 2013-01-11T12:53:28.753 回答
5

我在这段代码中看到的所有实例都是静态的。

因此,在 main 完成后,它们的析构函数在可执行文件的末尾被调用。

如果没有调用析构函数,那么这是一个错误。

于 2013-01-11T12:18:45.840 回答
4

当程序存在时,静态对象将被销毁。在 处设置断点~Foo2(),您将看到它或将日志写入文件应该可以帮助您诊断它。如果真的没有被调用,那么它是一个编译器错误。

在此处输入图像描述

上传图片来回答问题很有趣。

于 2013-01-11T12:26:37.050 回答
4

C++11 3.6.3/1:具有静态存储持续时间的已初始化对象的析构函数 [...] 作为从返回的结果被调用main

在程序从 中返回时mainanotherFoo已初始化;但foo2没有,因为GetFoo2在销毁anotherFoo. 因此,对规则的严格解释意味着不应调用其析构函数。

于 2013-01-11T12:51:13.203 回答