LINUX.ORG.RU

обработка исключения, генерируемого в shared object


0

0

Здравствуйте. Проблема такая: есть программа на C++, которая во время выполнения динамически подгружает некий shared object. Фукнции этого shared object могут кидать исключения, но эти исключения не ловятся в основной программе. И so и основная программа скомпилированны с опцией -fexceptions. Что может быть не так?


IMHO очевидную мантру
$ google "exceptions in shared object"
..уже пробовали.. ? :)

// wbr

klalafuda ★☆☆
()


собственно к примеру:

---cut---
http://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Link-Options.html#Link-Options

-shared-libgcc
-static-libgcc
On systems that provide libgcc as a shared library, these options force the use of either the shared or static version respectively. If no shared version of libgcc was built when the compiler was configured, these options have no effect.

There are several situations in which an application should use the shared libgcc instead of the static version. The most common of these is when the application wishes to throw and catch exceptions across different shared libraries. In that case, each of the libraries as well as the application itself should use the shared libgcc.

Therefore, the G++ and GCJ drivers automatically add -shared-libgcc whenever you build a shared library or a main executable, because C++ and Java programs typically use exceptions, so this is the right thing to do.

If, instead, you use the GCC driver to create shared libraries, you may find that they will not always be linked with the shared libgcc. If GCC finds, at its configuration time, that you have a non-GNU linker or a GNU linker that does not support option --eh-frame-hdr, it will link the shared version of libgcc into shared libraries by default. Otherwise, it will take advantage of the linker and optimize away the linking with the shared version of libgcc, linking with the static version of libgcc by default. This allows exceptions to propagate through such shared libraries, without incurring relocation costs at library load time.

However, if a library or main executable is supposed to throw or catch exceptions, you must link it using the G++ or GCJ driver, as appropriate for the languages used in the program, or using the option -shared-libgcc, such that it is linked with the shared libgcc.
---cut---

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

Не всё так просто.
Программа и so линкуются, используя g++, который по умолчанию использует shared-gcc. К тому же принудительное задание этого параметра тоже ничего не дало.

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

Вот стек исключения, который выдал gdb:

Program received signal SIGABRT, Aborted.
[Switching to Thread 8192 (LWP 30076)]
0x42028cc1 in kill () from /lib/i686/libc.so.6
(gdb) bt
#0 0x42028cc1 in kill () from /lib/i686/libc.so.6
#1 0x408f607d in raise () from /lib/i686/libpthread.so.0
#2 0x4202a019 in abort () from /lib/i686/libc.so.6
#3 0x403f1897 in __cxxabiv1::__terminate(void (*)()) (handler=0x8073b5c <abort>) at ../../../../gcc-3.2.3/libstdc++-v3/libsupc++/eh_terminate.cc:47
#4 0x403f18e4 in std::terminate() () at ../../../../gcc-3.2.3/libstdc++-v3/libsupc++/eh_terminate.cc:57
#5 0x403f1a66 in __cxa_throw () at ../../../../gcc-3.2.3/libstdc++-v3/libsupc++/eh_throw.cc:77
#6 0x4104292c in PSybaseDBConnection::CheckMessages() (this=0x818d8f0) at xmb_sybase.cxx:163

Функция CheckMessages() кидает исключение.
Ниже по стеку только пользовательские функции.

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

разгребать чужие bt без кода и малейшего намека на то, что это как и пр.? спасибо, это но это уже как-нить сами.

следующее замечательно работает в полном соответствии с документацией gcc:

---cut---
$ ls -l
total 16
-rw-r--r--  1 ianzag  wheel  168 Jan 17 23:57 Makefile
-rw-r--r--  1 ianzag  wheel  319 Jan 17 23:54 app.cc
-rw-r--r--  1 ianzag  wheel  119 Jan 17 23:49 foo.cc
-rw-r--r--  1 ianzag  wheel  351 Jan 17 23:52 foo.h

$ cat Makefile                
                                                                               
all: app

app: app.o libfoo.so
    g++ -o app -shared-libgcc -L . -Wl,-rpath . -lfoo app.o 

libfoo.so: foo.o
    g++ -shared -o libfoo.so foo.o

clean:
    rm -f *.o *.so app

$ cat app.cc              
                                                                                   
#include <iostream>
#include "foo.h"

int
main()
{
    try {
        std::cout << "Calling foo()" << std::endl;
        foo();
    } catch (const error &e) {
        std::cout << "Got \'" << e << "\' exception" << std::endl;
    } catch (...) {
        std::cout << "Unknown exception" << std::endl;
    }
    std::cout << "Done" << std::endl;
    return 0;
}

$ cat foo.h

#ifndef _FOO_H_
#define _FOO_H_

#include <ostream>

class error {
public :
    error(int e) : e_(e) { }

    std::ostream &put(std::ostream &os) const {
        os << std::dec << "error " << e_;
        return os;
    }

private :
    int e_;
};

inline std::ostream &
operator << (std::ostream &os, const error &e)
{
    return e.put(os);
}

void foo();

#endif // !_FOO_H_

$ cat foo.cc

#include <iostream>
#include "foo.h"

void
foo()
{
    std::cout << "foo() is called" << std::endl;
    throw error(123);
}

$ make 
c++ -O2  -c app.cc
c++ -O2  -c foo.cc
g++ -shared -o libfoo.so foo.o
g++ -o app -shared-libgcc -L . -Wl,-rpath . -lfoo app.o

$ ldd ./app
./app:
        -lstdc++.5 => /usr/lib/libstdc++.so.5
        -lm.0 => /usr/lib/libm387.so.0
        -lm.0 => /usr/lib/libm.so.0
        -lgcc_s.1 => /usr/lib/libgcc_s.so.1
        -lfoo => ./libfoo.so
        -lc.12 => /usr/lib/libc.so.12

$ ./app                                                                                                     
Calling foo()
foo() is called
Got 'error 123' exception
Done

$ g++ --version
g++ (GCC) 3.3.3 (NetBSD nb3 20040520)
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

---cut---

попробуйте воспроизвести это на вашей системе. AFAIU тут дело не совсем в передаче исключения между разделяемыми объектами.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

исходя из

>Program received signal SIGABRT, Aborted. >[Switching to Thread 8192 (LWP 30076)] >0x42028cc1 in kill () from /lib/i686/libc.so.6

поддерживаю

SIGABRT не только исключения посылают

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

> SIGABRT не только исключения посылают

ну в данном случае достаточно очевидно, что это генерация повторного исключения в деструкторе -> законный std::terminated() so левый SIGABRT ту не причем. собственно к передаче исключений через разделяемые библиотеки это отношения иметь не должно и скорее ошибка в программе.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

Причина оказалась простая: версия заголовочных файлов не соответствовала версии библиотеки libgcc.so.

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