gcc链接器扩展__attribute __((构造函数))导致main()崩溃

问题描述 投票:2回答:3

首先我有一个singleton.cpp文件来构建一个单例对象,并使用attribute((constructor))声明实例

#include<iostream>
using namespace std;
class singleton{
public:
    singleton(){cout<<"singleton ctor\n";}
};
__attribute__((constructor)) static void beforeFunction()
{
    printf("beforeFunction\n");
    singleton obj;
}

还有一个简单的main.cpp

#include<iostream>
using namespace std;
int main(){
    return 0;
}

我一起构建main.cpp singleton.cpp:

g++ singleton.cpp main.cpp -o main

./main
beforeFunction
Segmentation fault

那么为什么我的程序崩溃了,发生了什么?怎么解决?我在ubuntu上使用gcc。非常感谢。

constructor linker attributes g++ elf
3个回答
2
投票

我用g++ (Debian 7.3.0-5)g++ (GCC) 9.0.0 20180902 (experimental)复制了这个。

有趣的是,这失败了:

$ g++ singleton.cpp main.cpp && ./a.out
beforeFunction
Segmentation fault

但这按预期工作:

$ g++ main.cpp singleton.cpp && ./a.out
beforeFunction
singleton ctor

正如Acorn正确指出的那样,当你调用singleton构造函数时,iostream / std::cout机器尚未正确初始化。发生这种情况是因为main.o(只有main.o)发出了特殊代码,它调用了std::ios_base::Init::Init()。而且只是因为main.cpp有无关的#include <iostream>

怎么解决?

最好的解决方法是根本不使用__attribute__((constructor))。在您的情况下,没有理由做您正在做的事情。改为:

// singleton2.cpp
#include<iostream>
using namespace std;

class singleton{
  public:
    singleton(){cout<<"singleton ctor\n";}
};

static singleton obj;

使用上面的代码,链接的任何顺序都可以:

$ g++ main.cpp singleton2.cpp && ./a.out
singleton ctor

$ g++ singleton2.cpp main.cpp && ./a.out
singleton ctor

如果你坚持使用__attribute__((constructor)),那么在任何其他可以使用main.os的对象之前,确保iostream在你的链接线上。


1
投票

那么为什么我的程序崩溃了,发生了什么?

最有可能的是,qazxsw poi机器在qazxsw poi函数运行时尚未初始化。

怎么解决?

要么像Qazxswpoi一样使用C I / O,这似乎适合你的情况;或者更好,完全避免使用iostream(它不是标准C或C ++,即它使您的程序不可移植)。

请注意,__attribute__((constructor))不需要创建单例或全局对象。


1
投票

printf在静态C ++对象的帮助下初始化,请参阅__attribute__((constructor))

__attribute__((constructor))

因为你的代码都依赖于这个静态构造函数并且有一个ELF构造函数,所以它会遇到这个std::cout

但是,目前,未指定调用具有静态存储持续时间的C ++对象的构造函数和使用属性<iostream>修饰的函数的顺序。

如果您使用C ++对象,则订单是明确定义的。 GCC手册还建议使用 // For construction of filebuffers for cout, cin, cerr, clog et. al. static ios_base::Init __ioinit; ,但由于你不能将它应用于GCC limitation的定义(除了通过预处理器hackery),我不认为这在这种情况下有用。

© www.soinside.com 2019 - 2024. All rights reserved.