The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"Shared library, _init,_fini & C++ exceptions"
Вариант для распечатки Архивированная нить - только для чтения! 
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"Shared library, _init,_fini & C++ exceptions"
Сообщение от Меньшов Е.Н. emailИскать по авторуВ закладки on 04-Июл-02, 16:58  (MSK)
Возникла проблема: в библиотеке, написанной на C++ не обрабатываются исключения. Не обрабатываются по причине указания линкеру ld опций:
-nostartfiles
или
-nostdlibs

Эти опции необходимы для сборки, так как библиотека содержит функции
_init и _fini. Если не указывать эти опции, получим ошибку типа "multiple definition". Если указывать, то либа собирается, но исключения не перехватываются - сразу вызывается abort. Пример ниже:
-----------------------------------------------------------------------
//файл ex_dll.cpp
#include <stdio.h>

extern "C"
void _init()
{
}

extern "C"
void _fini()
{
}

void test()
{
  try
  {
    throw 10;  
  }
  catch(...)
  {
    printf("Exception Catched in %s %d\n",__FILE__,__LINE__);
  }
}
-----------------------------------------------------------------------
//файл ex_test.cpp:
#include <stdio.h>
void main()
{
    test();
}
-----------------------------------------------------------------------
//файл makefile:
CC = g++
PROG = test

$(PROG):libex_dll.so
$(CC) -L./ -lex_dll -fexceptions -fpic -g3 -o $(PROG) ex_test.cpp
strip $(PROG)


libex_dll.so:
$(CC)  -shared -fexceptions -nostdlib -g3 -o libex_dll.so ex_dll.cpp
#-fpic  -fexceptions -nostartfiles
clean:
rm -f *.o *.exe *.so $(PROG)
-----------------------------------------------------------------------
Суть примерно такая. Реальное приложения, естессно, посложнее, но приведенный пример точно отражает суть проблемы. Буду очень благодарен, если кто - то поможет енту проблему решить.
На всякий случай : OS: Linux (k 2.4.12); gcc 2.95.3 (хотя, похоже, это проблема компилера и линкера - под Solaris 7 была та же история).

  Рекомендовать в FAQ | Cообщить модератору | Наверх

 Оглавление

Индекс форумов | Темы | Пред. тема | След. тема
Сообщения по теме

1. "RE: Shared library, _init,_fini & C++ exceptions"
Сообщение от Арлекин emailИскать по авторуВ закладки on 05-Июл-02, 08:50  (MSK)
>Если указывать, то либа собирается, но исключения не перехватываются - сразу вызывается abort.
Ты как узнал, что SIGABRT выскакивает на throw ? Я почему-то думаю, что все дело в двойных _init()/_fini(). Если смотреть на твой приммер, то инициализатор ничего не делает, а ты уверен, что ничего не делает и тот, кого подменяют? И потом - как ты узнаЕшь когО вызвали ? Сделай себе маленький стек, клади туда имена функций при входе и убирай при  выходе. Так в джяве сделано. Стек пусть пишется на диск при каждом изменении. Тогда поймаешь точку вылета.

>//файл makefile:
>CC = g++
>PROG = test
>
>$(PROG):libex_dll.so
> $(CC) -L./ -lex_dll -fexceptions -fpic -g3 -o $(PROG) ex_test.cpp
А теперь "вопрос подхода". Зачем ты пытаешься шарную либу "намертво" прицепить к исполняемому файлу ?
Никто не запрещает так делать, но в таком случае таблицы ссылок строятся вместе, обнаруживаются перекрытия, начинаются твои проблемы с внешними именами. И выскакивает она не на исключении.
По-моему, наиболее верный путь использования .so - через вызовы семейства dlopen(). В итаком случае адресное пространство с точки зрния системы все-таки общее, а вот с точки зрения "строителей" - компилера и линкера - это разные программы. Возни больше, согласен, но и проблем меньше.
А в соляре вообще .so - какие-то не такие. Например кроме RTLD_GLOBAL она ни с чем другим нормально не работает... Да и 7-ка не лучший выбор для тестирования.

  Рекомендовать в FAQ | Cообщить модератору | Наверх

2. "RE: Shared library, _init,_fini & C++ exceptions"
Сообщение от Soldier Искать по авторуВ закладки on 05-Июл-02, 09:47  (MSK)
>Возникла проблема: в библиотеке, написанной на C++ не обрабатываются исключения. Не обрабатываются
>по причине указания линкеру ld опций:
>-nostartfiles
>или
>-nostdlibs
>
>Эти опции необходимы для сборки, так как библиотека содержит функции
>_init и _fini. Если не указывать эти опции, получим ошибку типа "multiple
>definition". Если указывать, то либа собирается, но исключения не перехватываются -
>сразу вызывается abort. Пример ниже:
>-----------------------------------------------------------------------
>//файл ex_dll.cpp
>#include <stdio.h>
>
>extern "C"
>void _init()
>{
>}
>
>extern "C"
>void _fini()
>{
>}
>
>void test()
>{
>  try
>  {
>    throw 10;
>  }
>  catch(...)
>  {
>    printf("Exception Catched in %s %d\n",__FILE__,__LINE__);
>  }
>}
>-----------------------------------------------------------------------
>//файл ex_test.cpp:
>#include <stdio.h>
>void main()
>{
>    test();
>}
>-----------------------------------------------------------------------
>//файл makefile:
>CC = g++
>PROG = test
>
>$(PROG):libex_dll.so
> $(CC) -L./ -lex_dll -fexceptions -fpic -g3 -o $(PROG) ex_test.cpp
> strip $(PROG)
>
>
>libex_dll.so:
> $(CC)  -shared -fexceptions -nostdlib -g3 -o libex_dll.so ex_dll.cpp
>#-fpic  -fexceptions -nostartfiles
>clean:
> rm -f *.o *.exe *.so $(PROG)
>-----------------------------------------------------------------------
>Суть примерно такая. Реальное приложения, естессно, посложнее, но приведенный пример точно отражает
>суть проблемы. Буду очень благодарен, если кто - то поможет енту
>проблему решить.
>На всякий случай : OS: Linux (k 2.4.12); gcc 2.95.3 (хотя, похоже,
>это проблема компилера и линкера - под Solaris 7 была та
>же история).


Я провел небольшой эксперемент, а именно - указал линкеру свои инициализационные/финализационные процедуры вместо дефалтовых _init и _fini,
после этого прога перестала катчить exception даже без указания опции -nostdlib компилеру. Отсюда вывод - дефалтовый _init  что-то проделывает для того, чтобы catch отрабатывала. Дальше копаться времени нет.


  Рекомендовать в FAQ | Cообщить модератору | Наверх

3. "RE: Shared library, _init,_fini & C++ exceptions"
Сообщение от Меньшов Е.Н. emailИскать по авторуВ закладки on 05-Июл-02, 10:19  (MSK)
Вот что выдает gdb:
--------------------------------------------------------------------------
men@penguin:~/work> gdb test
GNU gdb 20010316
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-suse-linux"...(no debugging symbols found)...
(gdb) run
Starting program: /home/men/work/test

Program received signal SIGABRT, Aborted.
0x400cf861 in kill () from /lib/libc.so.6
(gdb) bt
#0  0x400cf861 in kill () from /lib/libc.so.6
#1  0x400cf665 in raise () from /lib/libc.so.6
#2  0x400d0c81 in abort () from /lib/libc.so.6
#3  0x40056e48 in __default_terminate () from /usr/lib/libstdc++-libc6.2-2.so.3
#4  0x40056e6d in __terminate () from /usr/lib/libstdc++-libc6.2-2.so.3
#5  0x40057926 in throw_helper () from /usr/lib/libstdc++-libc6.2-2.so.3
#6  0x40057af5 in __throw () from /usr/lib/libstdc++-libc6.2-2.so.3
#7  0x40030680 in test () at ex_dll.cpp:21
#8  0x08048598 in __register_frame_info ()
#9  0x400be7ee in __libc_start_main () from /lib/libc.so.6
(gdb)
--------------------------------------------------------------------------
похоже, что- то неверно сработало в libstdc++. Простой выброс исключения не перехватывается, сразу вызывается __default_terminate. Ща залезу в исходники libstdc++ и поищу там. Предполагаю, что там криво сработала void _init() или что - то в этом духе. Спасибо за участие. Если у кого будут еще соображения - пишите.
p.s. 2Арлекин: Динамическая загрузка не канает. Библиотека довольно обширная и под нее уже написано много софта. Не думал, что при портации на пингвина возникнет подобная проблема...

  Рекомендовать в FAQ | Cообщить модератору | Наверх

4. "RE: Shared library, _init,_fini & C++ exceptions"
Сообщение от Сергей Трошин emailИскать по авторуВ закладки on 29-Ноя-02, 15:07  (MSK)
>Возникла проблема: в библиотеке, написанной на C++ не обрабатываются исключения. Не обрабатываются
>по причине указания линкеру ld опций:
>-nostartfiles
>или
>-nostdlibs
>
>Эти опции необходимы для сборки, так как библиотека содержит функции
>_init и _fini. Если не указывать эти опции, получим ошибку типа "multiple
>definition". Если указывать, то либа собирается, но исключения не перехватываются -

И это понятно, имена c __ зарезирвированы и пыпатся лезть туда - значит нарыватся на неприятности.
Существует ли другой способ автоматически инициализировать библиотеку?
Если нет, то надо использовать что-то типа:

static int need_init = 1;

int lib_init () {
  if ( need_init ) {
     need_init = 0;
     ...
  };
};

или же прибегнуть к механизмам конструкторов/деструкторов:
class AAA {
  public:
    AAA () {
      // init actions
    }
    ~AAA () {
      // fini actions
    }
};

static AAA foo; // Автоматически создаётся и разрушается

  Рекомендовать в FAQ | Cообщить модератору | Наверх


Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Пожалуйста, прежде чем написать сообщение, ознакомьтесь с данными рекомендациями.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру