首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在共享库中混合PIC和非PIC对象

在共享库中混合PIC和非PIC对象
EN

Stack Overflow用户
提问于 2011-11-30 19:06:19
回答 1查看 3.8K关注 0票数 6

这个问题与this one有关,也与它的答案有关。

我刚在我正在做的建筑中发现了一些丑陋。这种情况有点类似于以下情况(用gmake格式编写);注意,这特别适用于sparc和x86硬件上的32位内存模型:

代码语言:javascript
复制
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不太了解,也不知道它是否是个好主意/聪明。我猜想,在这种情况下,它是不需要的,而是会发生的,因为有人没有足够的兴趣去找出正确的方法,当在构建中加入新的东西时,就会找到正确的方法。

我的问题是:

  1. 是这个安全的
  2. 它是一个好主意
  3. 如果我把所有东西都切换到PIC会产生什么潜在的问题
  4. 有什么不明显的问题我可能需要注意.

g 211

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-04-05 19:41:50

忘了这个问题是我写的。

首先要作出一些解释:

  • 非PIC代码可能会被操作系统加载到内存中的任何位置。现代开放源码软件。加载完所有内容后,它将经历一个修复文本段(可执行部分结束)的阶段,以便正确地处理全局变量;为此,文本段必须是可写的。
  • PIC可执行数据可以由操作系统加载一次,并在多个用户/进程之间共享。然而,要使操作系统做到这一点,文本段必须是只读的--这意味着没有修复。编译代码是为了使用全局偏移表( GOT ),这样它就可以相对于GOT来解决全局问题,从而减少了修复的需要。如果一个共享对象是在不使用PIC的情况下构建的,则
  • ,尽管它受到强烈的鼓励,它似乎并不是绝对必要的;如果操作系统必须修复文本段,那么它就不得不将其加载到标记为读-写的内存中.它阻止了跨processes/users.
  • If共享一个可执行二进制文件构建/使用/ PIC,我不知道引擎盖下出了什么问题,但我看到一些工具变得不稳定(神秘崩溃等)。

答案如下:

  • 混合使用PIC /non,或者在可执行文件中使用PIC会导致难以预测和跟踪不稳定性。我对为什么没有技术解释。
    • ..。若要包含分段错误、总线错误、堆栈损坏以及可能更多的besides.

,请执行以下操作

共享对象中的非

  • 可能不会造成任何严重的问题,但如果库在进程和/或用户之间多次使用,则可能会导致更多的内存使用。

最新情况(4/17)

从那时起,我就发现了我以前见过的一些坠机的原因。为了说明:

代码语言:javascript
复制
/*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;
}

..。然后:

代码语言:javascript
复制
$ 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和每个包含违规头的库运行一次构造函数/析构函数--因此是双空闲的。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8331456

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档