2010-08-04 51 views
7

在Linux上,我从静态库中生成了一些C++代码,该静态库定义了一个全局变量。此全局变量的单个实例在引用其符号的两个共享库之间共享。在Linux上,为什么析构函数在C++中的全局变量的共享实例上运行两次?

当进程关闭并且运行静态终止阶段时,我看到此共享实例上的析构函数运行了两次!据推测,每个图书馆每卸载一次。

这个问题与我最近在这里看到的另一个密切相关:related question。这听起来像是一样的行为,但没有讨论它为什么会发生。

有没有人知道这种行为背后的理论解释?

+0

它应该只能由编译器生成的代码对每个变量运行一次。尝试在运行析构函数时获取变量的地址,以验证它是否是同一个对象。 – 2010-08-04 19:26:35

+0

也许你在一些智能指针类中存储了一个指向该对象的指针,该指针试图摧毁它的指针。 – 2010-08-04 19:28:11

+0

因此,全局仅在其中一个库(的编译单元)中定义? – Thomas 2010-08-04 19:30:38

回答

2

如果你拿一个裸指针并把它放在一个智能指针(两次)中,它将会破坏两次,每次一个容器的引用次数降到零。

因此,如果您将裸指针传递到两个库中,那就可以了。每个人都把它放在一个共享指针对象中,并且每个都会销毁。如果你可以在dtor期间看到堆栈回溯,那应该在两个库中显示它。

+1

使用任何常规调试器,应该很容易检查调用堆栈回溯并找出谁在调用此析构函数。 – Vargas 2010-08-05 14:46:05

0

C++有一个规则被称为“一个定义规则”:

每个程序都应该包含在该程序中使用的每个非内联函数或对象的只有一个定义;不需要诊断。定义可以在程序中显式出现,它可以在标准库或用户定义的库中找到,或者(在适当的时候)隐式定义(见12.1,12.4和12.8)。

维基百科有一个article,更详细地解释了这一点。

您还没有在您的问题中发布代码,所以我无法确定您的情况,但在the question you linked to中,问题的示例是在两个共享库中定义相同的变量。这违反了“一个定义规则”,这显然是动态链接器的最终化策略所依赖的,导致析构函数被调用两次。

相关问题