在另一个静态对象的析构函数内构造的静态对象的析构函数 [英] Destructor of a static object constructed within the destructor of another static object

查看:162
本文介绍了在另一个静态对象的析构函数内构造的静态对象的析构函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些析构函数的问题,在下面的代码:

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:


  1. 它说的析构函数必须在反向
    施工顺序。在你的情况下,这意味着 GetFoo2 中的
    静态对象必须在
    构造之前被销毁,这是自相矛盾的。

  1. 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 (或从
<$ c>返回),调用 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.

这篇关于在另一个静态对象的析构函数内构造的静态对象的析构函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆