前几天遇到的一个问题,说明的很清楚是要加上-fPIC重新编译,这个问题只有在64位系统中编译的时候才会出现。 -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code), 则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意 位置,都可以正确的执行。 这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

对于Makefile可以直接在CFLAGS后面直接加上-fPIC即可,

对于./configure可以在编译时直接输入命令“CFLAGS=-fPIC” ./configure

对于cmake生成的makefile则可以在CMakeList.txt或者cmake生成的CMakeCache.txt中加上-fPIC, CMAKE_CXX_FLAGS:STRING=-fPIC,CMAKE_C_FLAGS:STRING=-fPIC,CMAKE_EXE_LINKER_FLAGS:STRING=-fPIC

在 Linux 下制作动态链接库,“标准” 的做法是编译成位置无关代码(Position Independent Code,PIC),然后链接成一个动态链接库。经常遇到的一个问题是 -fPIC 是不是必需,因为好像不加经常也能正常运行,只是创建 .so 的时候会有一个警告。

搜索、试验了一下,答案似乎是这样:

(1) 通常的建议是始终加上 -fPIC 生成位置无关代码;

(2) AMD64 下,必须使用位置无关代码,否则连接失败:

relocation R_X86_64_32S against `a local symbol' can not be used when making a shared object; recompile with -fPIC

(3) IA32 下,连接成功,但有警告:

warning: creating a DT_TEXTREL in object.

这样的 .so 文件可以完全正常工作。

可执行文件在链接时就知道每一行代码、每一个变量会被放到线性地址空间的什么位置,因此这些地址可以都作为常数写到代码里面。对动态库,这就不行了,这要等到加载时才知道。无非下面两种方法:

(1) 可重定位代码(relocatable code):Windows DLL 以及不使用 -fPIC 的 Linux SO。

生成动态库时假定它被加载在地址 0 处。加载时它会被加载到一个地址(base),这时要进行一次重定位(relocation),把代码、数据段中所有的地址加上这个 base 的值。这样代码运行时就能使用正确的地址了。

(2) 位置无关代码(position independent code):使用 -fPIC 的 Linux SO。

这样的代码本身就能被放到线性地址空间的任意位置,无需修改就能正确执行。通常的方法是获取指令指针(如 IA32 的 EIP 寄存器)的值,加上一个偏移得到全局变量/函数的地址。

PIC vs. relocatable:

(1) PIC 的缺点主要就是代码有可能长一些。例如 IA32,由于不能直接使用 [EIP+constant] 这样的寻址方式,甚至不能直接将 EIP 的值交给其他寄存器,要用到 GOT(global offset table)来定位全局变量和函数。这样导致代码的效率略低。

(2) PIC 的加载速度稍快,因为不需要做重定位。

(3) 多个进程引用同一个 PIC 动态库时,可以共用内存。这一个库在不同进程中的虚拟地址不同,但操作系统显然会把它们映射到同一块物理内存上。对于可重定位代码,则必须为每个库都在物理内存中复制一份副本,因为需要修改其中的地址。当然,主流现代操作系统都启用了分页内存机制,这使得重定位时可以使用 COW(copy on write)来节省内存(32 位 Windows 就是这样做的);然而,页面的粒度还是比较大的(例如 IA32 上是 4KiB),至少对于代码段来说能节省的相当有限。

注:对于 AMD64,由于 AMD64 实现了 [RIP+constant] 的寻址方式,第 (1) 点不成立。

这样,把动态库编译成 PIC 只有好处没有坏处,因而 Linux AMD64 要求用于生成动态库的目标文件必须使用 -fPIC 编译也合情合理了。

前几天遇到的一个问题,说明的很清楚是要加上-fPIC重新编译,这个问题只有在64位系统中编译的时候才会出现。-fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。
本文详细讲述了PHP动态编译 出现 Cannot find autoconf的 解决 方法 。分享给大家供大家参考。具体 方法 如下: 在安装完PHP后,想动态编译PHP的memcache扩展库 复制代码 代码如下:cd memcache-2.2.5/ /usr/ local /webserver/php/bin/phpize ./configure –with-php-config=/usr/ local /webserver/php/bin/php-config 但是执行/usr/ local /webserver/php/bin/phpize时 出现 错误: 复制代码 代码如下:Configuring for: /usr/bin/ld: /usr/ local /lib/libjpeg.a(jcapimin.o): relocation R_X86_64_32S against `jpeg_natural_order' can not be u sed when making a shared object ; recompile with -fPIC 这意思是,在产生so的时候,...
LibXML Compile Error: relocation R_X86_64_32 against `a local symbol ' can not be u sed when making a shared object ; recompile with -fPIC -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),   则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意   位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固
//编译安装php 5.3.3 由于php5.3.X已经自带了php-fpm所以不需要打补丁 # sudo ./configure –prefix=/usr/ local /php-5.3.3 –with-mcrypt –with-gettext –with-mysql –with-gd –with-jpeg-dir –with-png-dir –with-curl –with-freetype-dir –enable-gd-native-ttf –enable-mbstring –enable-sockets –with-png-dir –with-pdo-mysql –enable-fpm –
ELF。Exucutable and Linkable Format,译为“可执行和可链接的格式”。 它是关于可执行文件、对象代码、共享库和内核导出的一种公共标准文件的格式定义,广泛应用于类unix系统。每个ELF文件由三个部分组成:Program header table、Sectoin header table、Data referred to above。 PIC。Po... echo "build ..." PWD=`pwd` ./configure --prefix=${PWD}/../arm --host=arm-linux CC=../../gcc/gcc-linaro-5.4.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc CFLAGS=-fPIC #make && make install echo "done" 我的总目标是:写一个mainApi.cpp的文件,这个文件提供API给外部用户使用。mainApi.cpp需要依赖其他模块生成的静态库(在lib文件下)。将mainApi.cpp编译 链接成一个.so动态库共外部使用。在编译的时候 出现 relocation R_X sudo ./configure --enable-nonfree --enable-pic --enable- shared sudo make sudo make install 重新编译遇到问题的库即可
启动MongoDB时,提示: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory [root@SnsWeb ~]# /usr/ local /mongodb/bin/mongod --dbpath=/usr/ local /mongodb/data --logpath /usr/ local /mongodb/logs/mongodb.log --fork /usr/ local /mongodb/bin/mongod: error wh
/usr/bin/ld: /usr/ local /lib/mysql/libz.a(compress.o): relocation R_X86_64_32 against `.rodata.str1.1′ can not be u sed when making a shared object ; recompile with -fPIC /usr/ local /lib/mysql/libz.a: co
上次 解决 了编译ffplay异常的问题 这次要将ffmpeg的库用起来,不过编译动态库的时候遇到了点问题: relocation R_X86_64_32 against `a local symbol ’ can not be u sed when making a shared object ; recompile with -fPIC 由于上次使用./configure默认配置,里面只编译了.a静态文件(可通过 ./configure --help 看到)。所以先把.so动态库也编译了。 推荐一开始配置./co
这个错误信息通常 出现 在Python的pickle模块使用过程中。pickle模块可以将Python对象序列化成字节流,方便存储和传输。然而,如果pickle遇到本地对象( local object ),就会抛出"AttributeError: can't pickle local object "的异常。 本地对象是指在函数内部定义的变量或者函数,它们的作用域仅限于函数本身。当使用pickle来序列化一个函数或者对象时,如果这个函数或对象中含有本地对象,pickle就无法处理这些本地对象,因为这些对象并没有和全局命名空间产生联系,无法被pickle读取和处理。 解决 这个问题的 方法 是,避免使用本地对象,或者对包含本地对象的函数或对象进行重构,使其不包含本地对象。如果实在无法避免,可以将函数中的本地对象转换成全局对象(比如将函数中的变量定义为全局变量)。这样虽然可以 解决 这个问题,但是也会破坏原本的程序结构和逻辑,因此需谨慎使用。