Problem with exception handling in shared libs on Solaris
Keller, Steve
SKeller@ea.com
Fri Dec 18 14:21:00 GMT 1998
All -
On Solaris, when a C++ exception is thrown from inside a shared library, the
program using the library will terminate. This is true with both egcs 1.1.1
and g++ 2.8.1. I did some spelunking, and contacted Mike Stump, who
suggested I rebuild egcs with the variable 'exceptions_via_longjmp' set to 1
instead of 2 (in except.c). I did, and it fixed the problem.
I think this is a serious bug, C++ exceptions should work properly from
within shared libraries, how else should we write code that is to be used by
many different programs on the same machine (or the same program executing
with multiple instances)? I am concerned about the possible overhead using
setjmp/longjmp, as well as the fact that there have been problems with this
mechanism in past versions of gcc.
Below is a small example program that demonstrates the problem. First make
it without the shared libs ("make USE_LIBS=") to verify it works properly,
then make again ("make USE_LIBS=1") and run the program again. On our
Solaris machines (both Sparc and x86) this program will abort.
Thanks,
Steve Keller
Software Engineer
Electronic Arts, Inc.
skeller@ea.com
***** Makefile *****
USE_LIBS = 1
CC_ARGS= -O3 -Wall -I.
AR= /usr/xpg4/bin/ar rc
LD= /usr/ccs/bin/ld -Bdynamic -G -o
.SUFFIXES:
.SUFFIXES: .cpp .cc .C .c .o .so
%.o: %.cpp
g++ $(CC_ARGS) -c $< -o $@
%.so: %.cpp
g++ -fpic $(CC_ARGS) -c $< -o $@
HEADERS = excp.h thrower.h
EXE = TestExcp
ifdef USE_LIBS
OBJECTS = main.o
ELIB = -lexcp
TLIB = -lthrower
else
OBJECTS = main.o excp.o thrower.o
ELIB =
TLIB =
endif
all: $(EXE)
clean:
$(RM) *.o *.so $(EXE) core
$(EXE) : $(OBJECTS) $(LIBS)
g++ $(OBJECTS) -o $(EXE) -L. $(ELIB) $(TLIB)
libexcp.so : excp.so
$(RM) libexcp.so
$(LD) libexcp.so excp.so
libthrower.so : thrower.so
$(RM) libthrower.so
$(LD) libthrower.so thrower.so
excp.o : excp.cpp $(HEADERS)
thrower.o : thrower.cpp $(HEADERS)
main.o : main.cpp $(HEADERS)
excp.so : excp.cpp $(HEADERS)
thrower.so : thrower.cpp $(HEADERS)
***** Sources *****
////////////////////////////////
// excp.h
#ifndef EXCP_H_
#define EXCP_H_
class excp
{
public:
excp() {}
excp(const excp &e) {}
virtual ~excp() {}
const char *GetText(); // Get error text
};
#endif // EXCP_H_
////////////////////////////
// excp.cpp
#include "excp.h"
const char *excp::GetText() {
return "Test Exception";
}
/////////////////////////////
// thrower.h
#ifndef THROWER_H_
#define THROWER_H_
#include "excp.h"
class thrower
{
public:
thrower() {}
~thrower() {}
void doit(bool throwit);
private:
excp ex;
};
#endif // THROWER_H_
/////////////////////////////////
// thrower.cpp
#include "thrower.h"
#include <iostream>
void thrower::doit(bool throwit) {
if (throwit) {
std::cout<< "About to throw an excp." << endl;
throw ex;
}
else {
std::cout << "Not going to throw." << endl;
}
}
///////////////////////////////////
// main.cpp
#include "excp.h"
#include "thrower.h"
#include <iostream>
int main() {
thrower t;
std::cout << "About to try exception handling." << endl;
try {
t.doit(false);
t.doit(true);
}
catch(excp ex) {
std::cout << "Caught exception in main: " << ex.GetText() << endl;
}
return 0;
}
More information about the Gcc-bugs
mailing list