在共享库的构建选项中添加“-rpath,/usr/lib”会导致segfault

前端之家收集整理的这篇文章主要介绍了在共享库的构建选项中添加“-rpath,/usr/lib”会导致segfault前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个你好世界的节目.
#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

可以解释为什么从链接选项中删除-rpath /usr/lib来解决库中加载的segfault?

解决方法

从跟踪中,您的程序似乎加载了相同模块的不同二进制文件,这些模块应该是相同的版本:

/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替代,但是我找不到文档来支持.

猜你在找的C&C++相关文章