シンボルの解像度が間違っているという問題があります。私のメイン プログラムは、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 に置き換えても役に立ちません。