10

私はハローワールドプログラムを持っています。

#include <stdio.h>
#include <stdlib.h>

int main()
{
    printf("hello world! \n");
    return 0;
}

-lmicroxmlライブラリにリンクするために、リンク段階でプログラムのビルドを追加しますlibmicroxml.so

プログラムを起動すると、セグメンテーション違反が発生します。セグメンテーション違反は、の負荷に関連していますlibmicroxml.so。ここで、私の hello world プログラム実行のトレースの後:

 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, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 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, -1, 0) = 0x777b3000
old_mmap(0x777b3000, 1572, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x777b3000
old_mmap(0x777c3000, 1648, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 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, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 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\0006\320\0\0\0004"..., 4096) = 4096
old_mmap(NULL, 147456, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7778f000
old_mmap(0x7778f000, 76928, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x7778f000
old_mmap(0x777b2000, 408, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x13000) = 0x777b2000
close(3)                                = 0
munmap(0x777dd000, 4096)                = 0
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=413076, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 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\253`\0\0\0004"..., 4096) = 4096
old_mmap(NULL, 503808, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x77714000
old_mmap(0x77714000, 405592, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x77714000
old_mmap(0x77787000, 7572, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x63000) = 0x77787000
old_mmap(0x77789000, 21036, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x77789000
close(3)                                = 0
munmap(0x777dd000, 4096)                = 0
open("/usr/lib/libgcc_s.so.1", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=169712, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 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\307\220\0\0\0004"..., 4096) = 4096
old_mmap(NULL, 237568, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x776da000
old_mmap(0x776da000, 169036, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x776da000
old_mmap(0x77713000, 1776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x29000) = 0x77713000
close(3)                                = 0
munmap(0x777dd000, 4096)                = 0
open("/usr/lib/libc.so.0", O_RDONLY)    = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=425968, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 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\267`\0\0\0004"..., 4096) = 4096
old_mmap(NULL, 516096, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7765c000
old_mmap(0x7765c000, 418924, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x7765c000
old_mmap(0x776d2000, 8176, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x66000) = 0x776d2000
old_mmap(0x776d4000, 21784, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x776d4000
close(3)                                = 0
munmap(0x777dd000, 4096)                = 0
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=413076, ...}) = 0
close(3)                                = 0
stat("/lib/ld-uClibc.so.0", {st_mode=S_IFREG|0755, st_size=28976, ...}) = 0
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=413076, ...}) = 0
close(3)                                = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x777dd000
set_thread_area(0x777e4440)             = 0
mprotect(0x77787000, 4096, PROT_READ)   = 0
mprotect(0x776d2000, 4096, PROT_READ)   = 0
mprotect(0x777da000, 4096, PROT_READ)   = 0
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Segmentation fault

DSOFLAGS=-Wl,-soname,libmicroxml.so.1,-rpath,/usr/lib -shared -fPIClibmicroxml ライブラリーのビルドで、ライブラリーのビルド (リンケージ・フェーズ) で使用されていることがわかりました。

-rpath,/usr/libオプションからを削除したので、新しいものはDSOFLAGS=-Wl,-soname,libmicroxml.so.1 -shared -fPIC

そして、ライブラリを再構築し、hello world プログラムを起動すると、セグメンテーション違反が消えます。

私はで構築しています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リンケージ オプションから を削除すると、ライブラリのロード時にセグメンテーション違反が修正される理由を説明できる人はいますか?

4

2 に答える 2

11

トレースから、あなたのプログラムは、同じバージョンであるはずの同じモジュールの異なるバイナリをロードしているようです:

/lib/libc.so.0(サイズ: 413076 バイト) /usr/lib/libc.so.0(サイズ: 425968 バイト)。

/lib/libgcc_s.so.1(サイズ: 78232 バイト) /usr/lib/libgcc_s.so.1(サイズ: 169712 バイト)。

これはおそらく-rpath、モジュール リンクで を使用すると、強制的に からモジュールをロードするために発生し/usr/libますが、プログラムが使用するデフォルトの検索パスは( http://tldp.org/HOWTO/Program/libの dlopen ドキュメントによると) -Library-HOWTO/dl-libraries.html )。

したがって、プログラムがロードされます (最初にこのパスを検索しましたが、 が/usr/lib/libmicroxml.so.1見つからないことに注意してください)。/lib/libmicroxml.so.1次に、必要なモジュール (libgccおよびlibc) を からロードし続けます/lib。最後に、libmicroxmlこれらのモジュールを からロードする必要が/usr/libあるため (ビルド引数が提供されているため)、これらのモジュールもこのパスからロードされます。

同じ名前とインターフェイス (同じバージョンであるため) を持つ 2 つの異なるライブラリが一緒に読み込まれると、どの関数のどのバージョンが呼び出されたかがわからず、これにより矛盾が生じる可能性があります。

これは、あなたが行った方法、または-rpathプログラムのビルドに同じ引数を追加することで解決できると思います。

削除-rpathすることでこの問題が解決する理由は、 に必要なモジュールをロードするときlibmicroxmlに、ローダーが最初/libにデフォルトの最初のディレクトリとして検索し (他のディレクトリが指定されていないため)、このフォルダー内のモジュールが既に読み込まれているため、競合がないためです。

いずれにせよ、同じドライブに同じバージョンの同じモジュールの 2 つの異なるバイナリがあるというこの状況は、非常に不健全です。

GCC のバージョンに関しては、正しい libc または libgcc が以前の GCC で使用され (またはインストールされ)、新しい GCC に置き換えられたとしか思えませんが、それをサポートするドキュメントは見つかりませんでした。

于 2013-10-13T21:31:22.990 に答える
1

DSOFLAGS は次のようになります。

DSOFLAGS=-Wl,-soname,libmicroxml.so.1,-rpath,/usr/lib -shared -fPIC

このようにコンパイルしてみましたか?

gcc -L/usr/lib -Wl,-rpath=/usr/lib -Wall -o test main.c -lmicroxml

この方法でコンパイルできる場合は、Makefile でこの行と CC および CFLAGS を使用して、コンパイルを簡単にすることができます。リンクする方法は他にもいくつかあります。

このリンクの良い情報。

于 2013-10-19T17:05:27.217 に答える