这个问题与this one有关以及它的答案。
我刚刚在我正在处理的构建中发现了一些丑陋之处。情况看起来有点像下面(用gmake格式写的);请注意,这特别适用于 sparc 和 x86 硬件上的 32 位内存模型:
OBJ_SET1 := some objects
OBJ_SET2 := some objects
# note: OBJ_SET2 doesn't get this flag
${OBJ_SET1} : CCFLAGS += -PIC
${OBJ_SET1} ${OBJ_SET2} : %.o : %.cc
${CCC} ${CCFLAGS} -m32 -o ${@} -c ${<}
obj1.o : ${OBJ_SET1}
obj2.o : ${OBJ_SET2}
sharedlib.so : obj1.o obj2.o
obj1.o obj2.o sharedlib.so :
${LINK} ${LDFLAGS} -m32 -PIC -o ${@} ${^}
显然,它可以在共享对象中混合使用和不使用 PIC 编译的对象(这已经使用了多年)。我对 PIC 的了解不够,不知道它是否是一个好主意/聪明,我的猜测是在这种情况下不需要它,而是它正在发生,因为有人不太在乎找到正确的方法来做这件事关于构建的新内容。
我的问题是:
最佳答案
忘了我什至写了这个问题。
先按顺序做一些解释:
答案:
更新 (4/17)
从那以后,我发现了我之前看到的一些崩溃的原因。为了显示:
/*header.h*/
#include <map>
typedef std::map<std::string,std::string> StringMap;
StringMap asdf;
/*file1.cc*/
#include "header.h"
/*file2.cc*/
#include "header.h"
int main( int argc, char** argv ) {
for( int ii = 0; ii < argc; ++ii ) {
asdf[argv[ii]] = argv[ii];
}
return 0;
}
... 然后:
$ g++ file1.cc -shared -PIC -o libblah1.so
$ g++ file1.cc -shared -PIC -o libblah2.so
$ g++ file1.cc -shared -PIC -o libblah3.so
$ g++ file1.cc -shared -PIC -o libblah4.so
$ g++ file1.cc -shared -PIC -o libblah5.so
$ g++ -zmuldefs file2.cc -Wl,-{L,R}$(pwd) -lblah{1..5} -o fdsa
# ^^^^^^^^^
# This is the evil that made it possible
$ args=(this is the song that never ends);
$ eval ./fdsa $(for i in {1..100}; do echo -n ${args[*]}; done)
该特定示例可能不会最终崩溃,但基本上是该组代码中存在的情况。如果是 崩溃它可能会在析构函数中,通常是一个双重释放错误。
许多年前他们添加了
-zmuldefs
到他们的构建以摆脱多重定义的符号错误。编译器发出用于在全局对象上运行构造函数/析构函数的代码。 -zmuldefs
强制它们位于内存中的相同位置,但它仍然为 exe 和包含有问题的头文件的每个库运行一次构造函数/析构函数——因此是双重释放。
关于compiler-flags - 在共享库中混合 PIC 和非 PIC 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8331456/