#include <stdio.h> #include <stdlib.h> int main() { printf("hello world! \n"); return 0; }
我在链接阶段在程序的构建中添加-lmicroxml,以便链接到库libmicroxml.so
当我启动我的程序,我得到一个细分错误.分段故障与libmicroxml.so的负载有关.这里之后我的helleo世界程序的执行执行:
strace ./test execve("./test",["./test"],[/* 11 vars */]) = 0 old_mmap(NULL,4096,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|0x4000000,-1,0) = 0x777de000 stat("/etc/ld.so.cache",0x7f944760) = -1 ENOENT (No such file or directory) open("/lib/libmicroxml.so.1",O_RDONLY) = -1 ENOENT (No such file or directory) open("/lib/libmicroxml.so.1",O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/lib/libmicroxml.so.1",O_RDONLY) = 3 fstat(3,{st_mode=S_IFREG|0755,st_size=4129,...}) = 0 old_mmap(NULL,0) = 0x777dd000 read(3,"\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\4p\0\0\0004"...,4096) = 4096 old_mmap(NULL,69632,PROT_NONE,MAP_PRIVATE|MAP_ANONYMOUS,0) = 0x777b3000 old_mmap(0x777b3000,1572,PROT_READ|PROT_EXEC,MAP_PRIVATE|MAP_FIXED,3,0) = 0x777b3000 old_mmap(0x777c3000,1648,0) = 0x777c3000 close(3) = 0 munmap(0x777dd000,4096) = 0 open("/lib/libgcc_s.so.1",O_RDONLY) = 3 fstat(3,{st_mode=S_IFREG|0644,st_size=78232,"\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0006\320\0\0\0004"...,147456,0) = 0x7778f000 old_mmap(0x7778f000,76928,0) = 0x7778f000 old_mmap(0x777b2000,408,0x13000) = 0x777b2000 close(3) = 0 munmap(0x777dd000,4096) = 0 open("/lib/libc.so.0",O_RDONLY) = 3 fstat(3,st_size=413076,"\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\253`\0\0\0004"...,503808,0) = 0x77714000 old_mmap(0x77714000,405592,0) = 0x77714000 old_mmap(0x77787000,7572,0x63000) = 0x77787000 old_mmap(0x77789000,21036,MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS,0) = 0x77789000 close(3) = 0 munmap(0x777dd000,4096) = 0 open("/usr/lib/libgcc_s.so.1",st_size=169712,"\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\307\220\0\0\0004"...,237568,0) = 0x776da000 old_mmap(0x776da000,169036,0) = 0x776da000 old_mmap(0x77713000,1776,0x29000) = 0x77713000 close(3) = 0 munmap(0x777dd000,4096) = 0 open("/usr/lib/libc.so.0",st_size=425968,"\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\267`\0\0\0004"...,516096,0) = 0x7765c000 old_mmap(0x7765c000,418924,0) = 0x7765c000 old_mmap(0x776d2000,8176,0x66000) = 0x776d2000 old_mmap(0x776d4000,21784,0) = 0x776d4000 close(3) = 0 munmap(0x777dd000,...}) = 0 close(3) = 0 stat("/lib/ld-uClibc.so.0",st_size=28976,...}) = 0 open("/lib/libc.so.0",...}) = 0 close(3) = 0 old_mmap(NULL,0) = 0x777dd000 set_thread_area(0x777e4440) = 0 mprotect(0x77787000,PROT_READ) = 0 mprotect(0x776d2000,PROT_READ) = 0 mprotect(0x777da000,PROT_READ) = 0 --- SIGSEGV (Segmentation fault) @ 0 (0) --- +++ killed by SIGSEGV +++ Segmentation fault
在libmicroxml库的构建中,我发现它们在库的构建中(在链接阶段)使用DSOFLAGS = -Wl,-soname,libmicroxml.so.1,-rpath,/usr/lib -shared -fPIC.
我从选项中删除了-rpath /usr/lib,所以新的是DSOFLAGS = -Wl,-son,libmicroxml.so.1 -shared -fPIC
然后我重建图书馆,然后我启动了你好世界的程序,并且分割错误消失.
我用mips_gcc-4.6-linaro_uClibc-0.9.33.2构建
这个问题不是用我的旧gcc mips_gcc-4.3.3 cs_uClibc-0.9.30.1
解决方法
/lib/libc.so.0(size:413076 bytes)vs. /usr/lib/libc.so.0(size:425968 bytes).
/lib/libgcc_s.so.1(size:78232 bytes)vs. /usr/lib/libgcc_s.so.1(size:169712 bytes).
这可能是因为当您在模块链接中使用-rpath时,强制它从/usr/lib加载模块,但是您的程序使用的默认搜索路径是/ lib(根据http://tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html的dlopen文档).
所以:你的程序加载/usr/lib/libmicroxml.so.1(注意,它找不到/lib/libmicroxml.so.1,虽然它首先搜索这个路径).然后它继续从/ lib加载它需要的模块(libgcc和libc),最后,因为libmicroxml需要从/usr/lib加载这些模块(因为提供了构建参数),所以它们也从这个路径加载.
一旦将两个具有相同名称和接口的不同库(因为它们具有相同的版本)加载在一起,就不能知道调用哪个函数的版本,这可能会导致不一致.
我想你可以按照你所做的方式来解决这个问题,或者通过在程序的构建中添加相同的-rpath参数.
删除-rpath解决这个问题的原因是,当加载libmicroxml所需的模块时,加载程序首先搜索/ lib作为默认的第一个目录(因为没有指定其他目录),并且由于该文件夹中的模块已经加载,所以没有冲突.
在任何情况下,在同一驱动器上具有相同版本的同一模块的两个不同二进制文件的情况是非常不健康的.
对于GCC版本,我只能假设正确的libc或libgcc与以前的GCC一起使用(甚至安装了),并被更新的GCC替代,但是我找不到文档来支持.