473,804 Members | 2,190 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Shared Library Exceptions & Vague Linkage

First of all, sorry for duplicating this post. I put it up in the
alt.comp.lang.l earn.c-c++ mistakenly.

I'm investigating a problem whereby exceptions thrown from functions in
a Shared Library which was dynamically loaded (dlopen) are not properly
caught by the caller. Specifically, when compiling with G++ version
4.0, the RTTI data associated with the exception types is not being
properly aligned between the Shared Library and its caller.

The online manual for GCC describes this as a problem due to its
implementation of Vague Linkage, but does not fully explain how the
problem can be resolved.

I've been able to resolve the problem by taking the typeid of the
exception type before entering the try/catch block in the driver. This
is illustrated in the following code:

// DynamicLink.h
// **************

#ifndef dynamiclink_h
#define dynamiclink_h

#include <typeinfo>

namespace DynamicLink
{
I'm investigating a problem whereby exceptions thrown from functions in
a Shared Library which was dynamically loaded (dlopen) are not properly
caught by the caller. Specifically, when compiling with G++ version
4.0, the RTTI data associated with the exception types is not being
properly aligned between the Shared Library and its caller.

The online manual for GCC describes this as a problem due to its
implementation of Vague Linkage, but does not fully explain how the
problem can be resolved.

I've been able to resolve the problem by taking the typeid of the
exception type before entering the try/catch block in the driver. This
is illustrated in the following code:

// DynamicLink.h
// **************

#ifndef dynamiclink_h
#define dynamiclink_h

#include <typeinfo>

namespace DynamicLink
{

enum ExceptionType1
{
a = 0,
b = 1

};

extern "C" void throwExceptionT ype1();
typedef void (* throwExceptionT ype1_Fn)();

#ifdef FIX_VAGUE_LINKA GE

extern "C" void dumpRTTI();
typedef void (* dumpRTTI_Fn)();

char const * ExceptionType1_ _TypeId =
typeid(DynamicL ink::ExceptionT ype1).name();

#endif

}

#endif

// DynamicLink.cpp
// ***************

// build: g++ -DFIX_VAGUE_LINK AGE -g -shared -o libDynamicLink. so
DynamicLink.cpp

#include "DynamicLin k.h"

#include <stdio.h>

namespace DynamicLink
{

extern "C" void throwExceptionT ype1()
{
throw a;

}

#ifdef FIX_VAGUE_LINKA GE

extern "C" void dumpRTTI()
{
printf("Shared Library side RTTI:\n");
printf("typeid( ExceptionType1) : %s %p\n", ExceptionType1_ _TypeId,
ExceptionType1_ _TypeId);

}

#endif

}

// Driver.cpp
// *********

// build: g++ -DFIX_VAGUE_LINK AGE -g -fpic -o DynamicLinkDriv er -ldl
Driver.cpp

#include "DynamicLin k.h"
using namespace DynamicLink;

#include <stdio.h>
#include <dlfcn.h>

int main(int argv, char const * * arc)
{
void * lib = dlopen("./libDynamicLink. so", RTLD_NOW | RTLD_GLOBAL);

#ifdef FIX_VAGUE_LINKA GE

dumpRTTI_Fn dumpRTTI_fn = (dumpRTTI_Fn) dlsym(lib, "dumpRTTI") ;
dumpRTTI_fn();
printf("Driver side RTTI:\n");
printf("typeid( ExceptionType1) : %s %p\n", ExceptionType1_ _TypeId,
ExceptionType1_ _TypeId);

#endif

try
{
throwExceptionT ype1_Fn throwExceptionT ype1_fn =
(throwException Type1_Fn) dlsym(lib, "throwException Type1");
throwExceptionT ype1_fn();
}
catch (ExceptionType1 & e)
{
printf("caught ExceptionType1: %s %u - %u\n", __FILE__, __LINE__,
(int) e);
}
catch (...)
{
printf("caught unknown exception: %s %u\n", __FILE__, __LINE__);
}

dlclose(lib);

return 0;

}

// END CODE

If you compile the Shared Library and its associated executable driver
using the g++ commands given, then the proper exception handlers will
be executed. If you remove the -DFIX_VAGUE_LINK AGE directive from the
compile commands, then the catch (...) handler is erroniously executed.

The trick is putting the typeid(...) calls in the common header file.
Somehow this seems to resolve the typeid misalignment.

I would like to understand why this method is solving the problem, and
also if there is a better way to go about doing this. I suspect that
there is some combination of compiler / linker commands which can be
used, but I've yet to figure out which ones.

Thank you,

Albert Kennis
enum ExceptionType1
{
a = 0,
b = 1

};

extern "C" void throwExceptionT ype1();
typedef void (* throwExceptionT ype1_Fn)();

#ifdef FIX_VAGUE_LINKA GE

extern "C" void dumpRTTI();
typedef void (* dumpRTTI_Fn)();

char const * ExceptionType1_ _TypeId =
typeid(DynamicL ink::ExceptionT ype1).name();

#endif

}

#endif

// DynamicLink.cpp
// ***************

// build: g++ -DFIX_VAGUE_LINK AGE -g -shared -o libDynamicLink. so
DynamicLink.cpp

#include "DynamicLin k.h"

#include <stdio.h>

namespace DynamicLink
{

extern "C" void throwExceptionT ype1()
{
throw a;

}

#ifdef FIX_VAGUE_LINKA GE

extern "C" void dumpRTTI()
{
printf("Shared Library side RTTI:\n");
printf("typeid( ExceptionType1) : %s %p\n", ExceptionType1_ _TypeId,
ExceptionType1_ _TypeId);

}

#endif

}

// Driver.cpp
// *********

// build: g++ -DFIX_VAGUE_LINK AGE -g -fpic -o DynamicLinkDriv er -ldl
Driver.cpp

#include "DynamicLin k.h"
using namespace DynamicLink;

#include <stdio.h>
#include <dlfcn.h>

int main(int argv, char const * * arc)
{
void * lib = dlopen("./libDynamicLink. so", RTLD_NOW | RTLD_GLOBAL);

#ifdef FIX_VAGUE_LINKA GE

dumpRTTI_Fn dumpRTTI_fn = (dumpRTTI_Fn) dlsym(lib, "dumpRTTI") ;
dumpRTTI_fn();
printf("Driver side RTTI:\n");
printf("typeid( ExceptionType1) : %s %p\n", ExceptionType1_ _TypeId,
ExceptionType1_ _TypeId);

#endif

try
{
throwExceptionT ype1_Fn throwExceptionT ype1_fn =
(throwException Type1_Fn) dlsym(lib, "throwException Type1");
throwExceptionT ype1_fn();
}
catch (ExceptionType1 & e)
{
printf("caught ExceptionType1: %s %u - %u\n", __FILE__, __LINE__,
(int) e);
}
catch (...)
{
printf("caught unknown exception: %s %u\n", __FILE__, __LINE__);
}

dlclose(lib);

return 0;

}

// END CODE

If you compile the Shared Library and its associated executable driver
using the g++ commands given, then the proper exception handlers will
be executed. If you remove the -DFIX_VAGUE_LINK AGE directive from the
compile commands, then the catch (...) handler is erroniously executed.

The trick is putting the typeid(...) calls in the common header file.
Somehow this seems to resolve the typeid misalignment.

I would like to understand why this method is solving the problem, and
also if there is a better way to go about doing this. I suspect that
there is some combination of compiler / linker commands which can be
used, but I've yet to figure out which ones.

Thank you,

Albert Kennis

Jul 25 '06 #1
7 3396
I mixed up the message text - sorry again:

I'm investigating a problem whereby exceptions thrown from functions in
a Shared Library which was dynamically loaded (dlopen) are not properly
caught by the caller. Specifically, when compiling with G++ version
4.0, the RTTI data associated with the exception types is not being
properly aligned between the Shared Library and its caller.

The online manual for GCC describes this as a problem due to its
implementation of Vague Linkage, but does not fully explain how the
problem can be resolved.

I've been able to resolve the problem by taking the typeid of the
exception type before entering the try/catch block in the driver. This
is illustrated in the following code:

// DynamicLink.h
// **************

#ifndef dynamiclink_h
#define dynamiclink_h

#include <typeinfo>

namespace DynamicLink
{

enum ExceptionType1
{
a = 0,
b = 1

};

extern "C" void throwExceptionT ype1();
typedef void (* throwExceptionT ype1_Fn)();

#ifdef FIX_VAGUE_LINKA GE

extern "C" void dumpRTTI();
typedef void (* dumpRTTI_Fn)();

char const * ExceptionType1_ _TypeId =
typeid(DynamicL ink::ExceptionT ype1).name();

#endif

}

#endif

// DynamicLink.cpp
// ***************

// build: g++ -DFIX_VAGUE_LINK AGE -g -shared -o libDynamicLink. so
DynamicLink.cpp

#include "DynamicLin k.h"

#include <stdio.h>

namespace DynamicLink
{

extern "C" void throwExceptionT ype1()
{
throw a;

}

#ifdef FIX_VAGUE_LINKA GE

extern "C" void dumpRTTI()
{
printf("Shared Library side RTTI:\n");
printf("typeid( ExceptionType1) : %s %p\n", ExceptionType1_ _TypeId,
ExceptionType1_ _TypeId);

}

#endif

}

// Driver.cpp
// *********

// build: g++ -DFIX_VAGUE_LINK AGE -g -fpic -o DynamicLinkDriv er -ldl
Driver.cpp

#include "DynamicLin k.h"
using namespace DynamicLink;

#include <stdio.h>
#include <dlfcn.h>

int main(int argv, char const * * arc)
{
void * lib = dlopen("./libDynamicLink. so", RTLD_NOW | RTLD_GLOBAL);

#ifdef FIX_VAGUE_LINKA GE

dumpRTTI_Fn dumpRTTI_fn = (dumpRTTI_Fn) dlsym(lib, "dumpRTTI") ;
dumpRTTI_fn();
printf("Driver side RTTI:\n");
printf("typeid( ExceptionType1) : %s %p\n", ExceptionType1_ _TypeId,
ExceptionType1_ _TypeId);

#endif

try
{
throwExceptionT ype1_Fn throwExceptionT ype1_fn =
(throwException Type1_Fn) dlsym(lib, "throwException Type1");
throwExceptionT ype1_fn();
}
catch (ExceptionType1 & e)
{
printf("caught ExceptionType1: %s %u - %u\n", __FILE__, __LINE__,
(int) e);
}
catch (...)
{
printf("caught unknown exception: %s %u\n", __FILE__, __LINE__);
}

dlclose(lib);

return 0;

}

// END CODE

If you compile the Shared Library and its associated executable driver
using the g++ commands given, then the proper exception handlers will
be executed. If you remove the -DFIX_VAGUE_LINK AGE directive from the
compile commands, then the catch (...) handler is erroniously executed.

The trick is putting the typeid(...) calls in the common header file.
Somehow this seems to resolve the typeid misalignment.

I would like to understand why this method is solving the problem, and
also if there is a better way to go about doing this. I suspect that
there is some combination of compiler / linker commands which can be
used, but I've yet to figure out which ones.

Thank you,

Albert Kennis

Jul 25 '06 #2
On 24 Jul 2006 19:23:05 -0700, "akennis" <a_******@yahoo .comwrote in
comp.lang.c++:
First of all, sorry for duplicating this post. I put it up in the
alt.comp.lang.l earn.c-c++ mistakenly.

I'm investigating a problem whereby exceptions thrown from functions in
a Shared Library which was dynamically loaded (dlopen) are not properly
caught by the caller. Specifically, when compiling with G++ version
4.0, the RTTI data associated with the exception types is not being
properly aligned between the Shared Library and its caller.
[snip]

You're still in the wrong place. C++ does not have or define shared
libraries, dynamic loading, or dlopen().

news:comp.os.li nux.development .apps

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Jul 25 '06 #3

akennis wrote:
First of all, sorry for duplicating this post. I put it up in the
alt.comp.lang.l earn.c-c++ mistakenly.

I'm investigating a problem whereby exceptions thrown from functions in
a Shared Library which was dynamically loaded (dlopen) are not properly
caught by the caller. Specifically, when compiling with G++ version
4.0, the RTTI data associated with the exception types is not being
properly aligned between the Shared Library and its caller.

make certain that you have only one definition of the matching symbols
in all of your exceutable and shared libraries.
I guess this is being caused by having multiple copies of the matching
code inside the excecutable and again inside the shared library

Jul 25 '06 #4

Peter wrote:
make certain that you have only one definition of the matching symbols
in all of your exceutable and shared libraries.
I guess this is being caused by having multiple copies of the matching
code inside the excecutable and again inside the shared library
If the -DFIX_VAGUE_LINK AGE command is removed, then the only code
common between the shared library and the executable are the type &
function declarations in the header file. These are required inorder
to establish the shared library API.

I think that the type_info objects are being compiled into the binaries
automatically, and so these ARE present in both. How can I prevent the
type_info stuff from being compiled into the executable?

Thanks.

Jul 25 '06 #5

akennis wrote:
void * lib = dlopen("./libDynamicLink. so", RTLD_NOW | RTLD_GLOBAL);
....
dlclose(lib);

dlopen belongs into a constructor and dlclose into the matching
destructor.
If dlopen fails throw an exception containing the error information.

Jul 26 '06 #6

akennis wrote:
try
{
throwExceptionT ype1_Fn throwExceptionT ype1_fn =
(throwException Type1_Fn) dlsym(lib, "throwException Type1");
throwExceptionT ype1_fn();
}
catch (ExceptionType1 & e)

it is unlikely that you want to modify the exception inside the catch
block.
Thus catch a const reference of this type.

Jul 26 '06 #7

akennis wrote:
I mixed up the message text - sorry again:

I did not know that it is possible to get the typeid for an
enumeration.
Try again with a class which has at least one virtual function
-- e.g. derived from the standard exception class.

And also -- the call to dlsym() belongs into a C++ wrapper which checks
for success and throws an exception otherwise.
The assumption being that you write such a wrapper only once and reuse
it.
And another assumption being that at the place where you call dlopen()
you don't want to deal with the possibility that it may fail,
but you want to delegate this task to some piece of code up the stack.

Jul 26 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
3271
by: usr2003 | last post by:
I wrote the following test program to test the linkage directives extern "C": #include <stdio.h> extern "C" {
5
10534
by: Oliver | last post by:
Hi, I have a problem with a shared library of mine. I compile the *.o files and then generate the .so lib with: cc -shared libjava_vrpn.so *.o When I then run my program I get an error for an unresolved symbol. The symbols it's looking for are in another library called libvrpn.a, but for some unknown reason the compiler does not uses this library when I tell him to used.
20
3245
by: Steven T. Hatton | last post by:
I just read this in the description of how C++ is supposed to be implemented: "All external object and function references are resolved. Library components are linked to satisfy external references to functions and objects not defined in the current translation. All such translator output is collected into a program image which contains information needed for execution in its execution environment." What I'm wondering is what exactly...
19
2520
by: Deniz Bahar | last post by:
Hi, I would like to call one of my functions the exact name as an existing C library function (for example K&R2 exercises asks me to make an atof function). If I don't include the header with the declaration for the C library function (stdlib.h in this case) then define/declare my own function with the same name, am I safe? It seems to work on my compiler, but I wonder if this is portable or even acceptable? thx
0
1386
by: George P Boutwell | last post by:
I've got an 'third-party' library that had an library.sln for 2003.. I've opened that in VS 2005. I've modified the library and the test application that are part of that to enabled exceptions (the exceptions that where being used didn't work with /clr, so I changed them to the kind that did), and then I enabled /clr for both of them. The library builds fine, but then the test application fails to link with it (#using failed to load...
3
2252
by: tropos | last post by:
(Platform: Solaris with gmake and native Sun C++ compiler) Problem: If I create a shared object (.so file) and load it into a executable, the loader correctly runs constructors of static objects in the .so file. But if I link the same code statically, with no shared object, then the constructors don't run at all! Why?? Here's an example: <file AnnounceConstruction.cpp>
3
2226
by: djbaker | last post by:
Greetings, I am trying to create a class library/dll with C++ and I am running into a lot of trouble. I know that this is a C++ forum and not one specific to windows or VS 2005 but I'm hoping someone call help me. I would like to create a class library so that I can put classes that I reuse a lot into their own modules. I played around with it for awhile and had no luck. It was really easy to do in C# but C++ does not seem to be so...
3
3275
by: Bala | last post by:
Hello, I am trying to create a shared library on solaris. The inputs to this library is a source file and then 2 static libraries. I need to call code within the shared library in another application which in turn will use the static libraries for further processing. This is the command i am using to build the shared library
3
1834
by: HelloLinux | last post by:
The following is how I encouted my problems: 1) Compile print.cpp into libprint.so by Sun C++ 5.9.The command is: CC -G -KPIC -o libprint.so print.cpp It succeeds. 2)Compile debug.cpp into libdebug.so by g++ 3.4.6, debug.cpp calls a function defined in libprint.so. The command is: g++ -shared -fPIC -o libdebug.so debug.cpp -lprint -L. It succeeds too.
0
9714
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9594
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10600
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10351
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7638
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5534
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5673
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4311
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3834
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.