Конфликт имен при динамической загрузке
От: Eugene Kilachkoff Россия  
Дата: 22.11.04 10:06
Оценка:
Нарвалсь вот на такое странное поведение. Дано:
1. Наша система. Язык реализации — C++. В системе реализован класс с именем, скажем, CFoo. Ну, то есть, в основном бинарнике находятся реализации CFoo::CFoo(), CFoo::~CFoo() и некоторых методов.
2. Сторонняя библиотека (.so). Реализована также на C++, однако наружу торчит только C-style API, типа LibObject_Create(), LibObject_Work(), LibObject_Delete(). В частности, эти три функции являются оберткой для создания и удаления класса с именем ... правильно, CFoo

Мы загружаем библиотеку с помощью dlopen, резолвим LibObject_Create() и иже с ним, и начинаем с ней работать. Ну, все совершенно просто
LibObject *o = LibObject_Create();
int result = LibObject_Work(o,some_data);
cout << result << endl;
LibObject_Delete(o); // ( !!! )


В момент вызова LibObject_Delete прибегает пушной зверек А именно, вызывается наш деструктор для CFoo, только в качестве аргумента ему передается указатель на их CFoo, контролируемый оберткой с помощью LibObject *o. Естественно, у него съезжает крыша и наступает локальное помешательство, заканчивающееся SIGSEGV.
Дизассембер вполне четко показывает, что это не просто вызов куда попало (и попало почему-то к нам), а просто оно так отрезолвилось. В исходном сошнике это место указано в таблице релокаций, ну и линкер туда благополучно пихает указатель на нашу функцию. Переименование нашего класса CFoo в CBar лечит проблему, но это же не наш метод !!
Посему вопрос: какого, собсно, оно так делает ?
В тестовом примере воспроизвести не удалось — резолвится как нужно.

Система — linux с glibc 2.3 (whitebox respin1)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.