Скомпилировать программу C с помощью dlopen и dlsym с помощью -fPIC

У меня проблема с неправильным разрешением символа. Моя основная программа загружает общую библиотеку с dlopen и символ из нее с dlsym. И программа, и библиотека написаны в C. Библиотечный код

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

Чтобы заставить его работать на 64-битной машине, -fPIC передается gcc при компиляции.

Программа:

 #include  #include  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 %dd is %d\n",b,d); return 0; } 

Все работает нормально, если программа НЕ скомпилирована с -fPIC, но при сбое программы с -fPIC сбой происходит с ошибкой сегментации. Исследование показало, что авария вызвана неправильным разрешением символа a. Авария происходит, когда вызывается a, независимо от того, из библиотеки или основной программы (последняя получается путем комментирования строки, вызывающей c () в основной программе).

Не возникает проблем при вызове c (), возможно, потому, что c () не внутренне вызывается самой библиотекой, а () является одновременно функцией, используемой внутри библиотеки, и функцией API библиотеки.

Простым обходным решением не является использование -fPIC при компиляции программы. Но это не всегда возможно, например, когда код основной программы должен быть в самой общей библиотеке. Другим обходным решением является переименование указателя на функцию a на что-то другое. Но я не могу найти никакого реального решения.

Замена RTLD_LAZY на RTLD_NOW не помогает.

Я подозреваю, что между двумя глобальными символами происходит столкновение. Одним из решений является объявление a в основной программе как статическое. В качестве альтернативы, в man- RTLD_DEEPBIND linux упоминается флаг RTLD_DEEPBIND , расширение только для Linux, которое вы можете передать в dlopen и это приведет к тому, что библиотека предпочтет свои собственные символы над глобальными символами.

Кажется, эта проблема может иметь место в еще одном случае (например, для меня). У меня есть программа и несколько динамически связанных библиотек. И когда я попытался добавить еще один, я использовал функцию из статической lib (тоже мой). И я забыл добавить в список ссылок этот статический lib. Linker не предупреждал меня об этом, но программа искажала ошибку сегментации.

Может быть, это поможет кому-то.