6

シンボルの解像度が間違っているという問題があります。私のメイン プログラムは、dlopen を使用して共有ライブラリをロードし、そこから dlsym を使用してシンボルをロードします。プログラムとライブラリの両方が C で記述されています。ライブラリ コード

int a(int b)
{
  return b+1;
}

int c(int d)
{
  return a(d)+1;
}

64 ビット マシンで動作させるために、コンパイル時に -fPIC が gcc に渡されます。

プログラムは次のとおりです。

#include <dlfcn.h>
#include <stdio.h>

int (*a)(int b);
int (*c)(int d);

int main()
{
  void* lib=dlopen("./libtest.so",RTLD_LAZY);
  a=dlsym(lib,"a");
  c=dlsym(lib,"c");
  int d = c(6);
  int b = a(5);
  printf("b is %d d is %d\n",b,d);
  return 0;
}

プログラムが -fPIC でコンパイルされていない場合はすべて正常に動作しますが、プログラムが -fPIC でコンパイルされている場合はセグメンテーション違反でクラッシュします。調査の結果、クラッシュはシンボル a の不適切な解決が原因であることが判明しました。クラッシュは、ライブラリからでもメイン プログラムからでも、a が呼び出されたときに発生します (後者は、メイン プログラムで c() を呼び出す行をコメント アウトすることによって取得されます)。

c() 自体を呼び出しても問題は発生しません。おそらく、c() はライブラリ自体によって内部的に呼び出されないためですが、a() はライブラリによって内部的に使用される関数であり、ライブラリの API 関数でもあります。

簡単な回避策は、プログラムのコンパイル時に -fPIC を使用しないことです。しかし、これは常に可能であるとは限りません。たとえば、メイン プログラムのコードを共有ライブラリ自体に配置する必要がある場合などです。もう 1 つの回避策は、関数 a へのポインターの名前を別のものに変更することです。しかし、私は本当の解決策を見つけることができません。

RTLD_LAZY を RTLD_NOW に置き換えても役に立ちません。

4

3 に答える 3

4

2 つのグローバル シンボルの間に衝突があると思われます。a1 つの解決策は、メイン プログラムで static として宣言することです。または、Linux のマンページにはRTLD_DEEPBIND、Linux 専用の拡張機能であるフラグが記載されています。これを渡すとdlopen、ライブラリがグローバル シンボルよりも独自のシンボルを優先するようになります。

于 2012-05-26T10:18:25.930 に答える