LINUX.ORG.RU

[dlopen] segfault при загрузке библиотеки


0

0

Доброе время суток.
Есть такая проблема:
Програма А использует ф-ии из libB.so
LibB.so использует ф-ции из libC.so через dlopen.
В результате segfault.
Если А использует libC.so напрямую (через dlopen) всё в порядке.
В чём может быть проблема?
п.с. возвращаемые значения dlopen и dlsym проверяются, нулю не равны.
Спасибо.

Ответ на: комментарий от Deleted
#0  0x002df489 in ?? () from /lib/tls/i686/cmov/libc.so.6
#1  0x002e1978 in malloc () from /lib/tls/i686/cmov/libc.so.6
#2  0x001f6bb7 in operator new(unsigned int) () from /usr/lib/libstdc++.so.6
#3  0x003c4558 in okUsbFrontPanel_Construct () from ./scDevice2DLL.so
#4  0x0804ed9f in okUsbFrontPanel_Construct () at okFrontPanelDLL.cpp:1082
#5  0x0804d175 in okCUsbFrontPanel (this=0x86fe578) at okFrontPanelDLL.cpp:164
#6  0x003c4566 in okUsbFrontPanel_Construct () from ./scDevice2DLL.so
#7  0x0804ed9f in okUsbFrontPanel_Construct () at okFrontPanelDLL.cpp:1082
#8  0x0804d175 in okCUsbFrontPanel (this=0x86fe538) at okFrontPanelDLL.cpp:164
#9  0x003c4566 in okUsbFrontPanel_Construct () from ./scDevice2DLL.so
#10 0x0804ed9f in okUsbFrontPanel_Construct () at okFrontPanelDLL.cpp:1082
#11 0x0804d175 in okCUsbFrontPanel (this=0x86fe4f8) at okFrontPanelDLL.cpp:164
#12 0x003c4566 in okUsbFrontPanel_Construct () from ./scDevice2DLL.so
#13 0x0804ed9f in okUsbFrontPanel_Construct () at okFrontPanelDLL.cpp:1082
#14 0x0804d175 in okCUsbFrontPanel (this=0x86fe4b8) at okFrontPanelDLL.cpp:164
#15 0x003c4566 in okUsbFrontPanel_Construct () from ./scDevice2DLL.so
#16 0x0804ed9f in okUsbFrontPanel_Construct () at okFrontPanelDLL.cpp:1082
#17 0x0804d175 in okCUsbFrontPanel (this=0x86fe478) at okFrontPanelDLL.cpp:164
#18 0x003c4566 in okUsbFrontPanel_Construct () from ./scDevice2DLL.so
#19 0x0804ed9f in okUsbFrontPanel_Construct () at okFrontPanelDLL.cpp:1082
#20 0x0804d175 in okCUsbFrontPanel (this=0x86fe438) at okFrontPanelDLL.cpp:164
#21 0x003c4566 in okUsbFrontPanel_Construct () from ./scDevice2DLL.so
#22 0x0804ed9f in okUsbFrontPanel_Construct () at okFrontPanelDLL.cpp:1082
---Type <return> to continue, or q <return> to quit---

и так дальше в таком духе. Очень длинный.

nanoo_linux
() автор топика

>>В чём может быть проблема?

Проблема может быть в том, как ты вызываешь dlopen(). Там же есть RTLD_LAZY, RTLD_NOW и другие флаги.

MuZHiK-2 ★★★★
()
Ответ на: комментарий от MuZHiK-2

От производителя RTLD_NOW стоит. Я пробовал менять на lazy - не помогает. || GLOBAL/LOCAL тоже не канает.

nanoo_linux
() автор топика
Ответ на: комментарий от nanoo_linux

>>и так дальше в таком духе. Очень длинный.

Судя по всему, ты попадаешь в бесконечную рекурсию. Скорее всего, у тебя в двух библиотеках определены символы (имена функций или объектов) с одинаковыми именами. И первый пытается вызвать второго, а второй, в свою очередь - первого. Все из-за того, что все загружаемые для приложения символы находятся в одном пространстве имен. Посмотри имена переменных внимательно.

MuZHiK-2 ★★★★
()
Ответ на: комментарий от MuZHiK-2

Да, есть такое дело.
В libB.so определа ф-я ф1. Она через указататель, полученый из dlsym вызывает ф1, только из libC.so. Выходит, что конструкция

int p(){..};//*
int (*_p)();
void *h = dlopen("libC.so", RTDL_NOW);
_p = dlsym(h, "p");
кладёт в _p адрес ф-и помеченой *. Так?
Мне не ясен этот момент. Ведь h то указывает на libC.so. Почему тогда dlsym мне возвращает адрес ф-и из другой библиотеки?
Подозреваю, что это особенность динамического линкера.

nanoo_linux
() автор топика
Ответ на: комментарий от nanoo_linux

>>Ведь h то указывает на libC.so

h-файл никуда не указывает - он только содержит имена символов для линкера.

Почему тогда dlsym мне возвращает адрес ф-и из другой библиотеки?

Потому что когда линкер резолвит все символы и ссылки, то все библиотеки и приложение попадают в один «котел», вот потому и получается так, что найдя символ в одной либе, выставляет ссылку на символ с таким же именем в другой либе.

MuZHiK-2 ★★★★
()
Ответ на: комментарий от nanoo_linux

>Подозреваю, что это особенность динамического линкера.

1. Попробуй еще флаг RTLD_LOCAL

2. Можно узнать, из какой библиотеки используется символ:

#define _GNU_SOURCE
// ....
#include <dlfcn.h>
// ....

int p(){..};//* 
int (*_p)(); 
Dl_info di;
void *h = dlopen("libC.so", RTDL_NOW); 
_p = dlsym(h, "p");
if (dladdr(_p, &di))
  printf("using symbol p from %s\n", di.dli_fname);
linuxfan
()
Ответ на: комментарий от MuZHiK-2

h-файл никуда не указывает

Имеется ввиду не h файл а void* h, дескриптор библиотеки от dlopen. Изивините за неудачное имя переменной.

Потому что когда линкер резолвит все символы и ссылки

Я так понимаю это происходит после вызова dlopen? Мне кажется, что мы с вами о разных вещах говорим.

nanoo_linux
() автор топика
Ответ на: комментарий от linuxfan

1.

Пробовал, не помогает.

Проблему я решил, но сам не понял как.
Дело было вот в чём. В хидере к этой библиотеке есть класс с названием name. Всё что он делает - вызывает С ф-ии из библиотеки. Это С ф-ии начинаюстся с name. Есть и ф-ия name_Construct и name_Destruct, вызываются из коструктора и деструктора класса соответсвенно.
Так вот прикол в чём, когда я делаю new name (а именно тут сегфолт происходит) конструктор пытается вызвать name_Construct, но (!) вызывает сам себя. Отсюда и рекурсия без возможности выхода. Результат - переполненый стек и сегфолт.
Если имя класса этого поменять на что либо другое кроме name - всё работает.

Кто нибудь слышал, что бы линкер вместо С ф-ий <n>_Construct вызывал конструктор класса с именем <n>?
Лично я впервые с таким встречаюсь. Думаю этот shared object так написан. Толи запакован чем-то, толи заголовки кривые, толи ещё что.
В общем не понятный глюк какой-то.

nanoo_linux
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.