gcc,c++:静态字符串成员变量导致堆损坏/分段错误

Posted

技术标签:

【中文标题】gcc,c++:静态字符串成员变量导致堆损坏/分段错误【英文标题】:gcc, c++: static string member variarible causes heap corruption/segmentation fault 【发布时间】:2010-08-19 15:09:14 【问题描述】:

我有一个使用动态加载库的大型应用程序。在程序结束时终止它时会出现段错误或吐出一条消息“glibc 检测到损坏的双链表”。查看 valgrind 输出,我认为情况就是这样: 假设我们有三个文件:

utilities.c        - compiled with -fPIC and used ar and ranlib to create utilities.a.
dynamicallyloaded.c- compiled with -fPIC and -shared and linked with utlities.a to generate dynamicallyloaded.so 
main.c             - compiled with -fPIC and linked with utilities.a to create main. main dynamically loads and uses dynamicallyloaded.so .
utilities.h        - delclared a class IfTrackerFile with AubFileName as a static string member like   static string          AubFileName;

utilities.cpp      - defines the static variable: string IfTrackerFile::AubFileName;

valgrind out 表示该行存在无效的 free/delete/delete : 字符串 IfTrackerFile::AubFileName;

我不知道发生了什么。 非常感谢这方面的任何帮助/指导。

【问题讨论】:

使用静态库并非易事。将所有内容编译为共享库并让编译器对其进行排序。 【参考方案1】:

我猜你最终得到了两个不同的IfTrackerFile::AubFileName 副本。一种是直接从utilities.a 将其拉入您的程序,另一种是在您动态加载dynamicallyloaded.so 时。我猜这让系统在程序关闭时破坏所有静态和全局对象感到困惑,而你最终调用了两次析构函数。

我认为您不应该以这种方式混合 .a 和 .so 文件。基本上,一个好的经验法则是永远不要将.so 文件与.a 链接,即使您将-fPIC 代码放在.a 中也是如此。

【讨论】:

【参考方案2】:

这是在黑暗中拍摄的,但问题可能是全局对象。将类实例化为全局变量意味着该变量在调用 main() 之前被实例化。这意味着在 main() 开始之前调用构造函数,在 main 完成后调用析构函数。构造函数和析构函数的调用顺序也是不确定的。

我的建议是将所有全局对象(不是普通旧数据的全局变量 - POD - 类型)转换为在 main 开头实例化并在 main 结尾销毁的指针。

【讨论】:

以上是关于gcc,c++:静态字符串成员变量导致堆损坏/分段错误的主要内容,如果未能解决你的问题,请参考以下文章

gcc找不到静态库中的函数

C++分段错误中的堆算法

c++中静态成员变量和静态成员函数(笔试经历)

操作系统中的内存分区

MSVC 导致静态 const 模板成员初始化失败

java里的静态成员变量是放在了堆内存还是栈