Re: Catching C++ exceptions thrown from a framework
Re: Catching C++ exceptions thrown from a framework
- Subject: Re: Catching C++ exceptions thrown from a framework
- From: Steve Baxter <email@hidden>
- Date: Tue, 18 Jul 2006 16:03:39 +0100
Hi Howard,
On 18 Jul 2006, at 15:39, Howard Hinnant wrote:
Hi Steve,
By forcing the type (i.e. the type_info data) to be both visible
and have weak linkage, the linker will unique all type_info data
across shared library boundaries. This has the effect of making
the by-address comparison the same as the by-name comparison since
the linker is guaranteeing there will be no hidden (and duplicate)
RTTI data.
Does this still work if you use CFBundle to load your code? CFBundle
loads DLLs with private visibility which breaks all the RTTI fixes.
I have been told that this "behaves correctly".
Basically we want the same behaviour as CW and VC++ - the performance
"improvement" of the Xcode way is negligible (who needs high-
performance exceptions) and causes a lot of trouble! This all used
to work - Xcode's approach has stopped it working.
This should be used as a transitional flag or "quick fix" flag.
The more robust approach is to decorate your sources with
visibility attributes (or pragmas).
This is not exactly a developer-friendly option - why is this not a
permanent fix? What does it actually do?
Can I beg once more for Apple to compile the runtimes to compare
using type names not type_info addresses? This is a single switch
that would make all this pain go away for everyone.
Cheers,
Steve.
-Howard
On Jul 18, 2006, at 10:23 AM, Steve Baxter wrote:
Hi Chris,
Hmm, odd that DTS didn't mention this when I asked them
specifically about this problem!
Does -fvisibility-ms-compat force RTTI comparison to happen by
type name rather than type ID address (i.e. the same class
implemented in two different plugins will be considered to be the
same for RTTI even though the typeid for the types will have
different addresses)?
How does it do this without changing the C++ runtime (I believe
the problem here is in the runtime as installed by the OS rather
than in Xcode)?
Cheers,
Steve.
On 18 Jul 2006, at 14:22, Chris Espinosa wrote:
On Jul 18, 2006, at 2:03 AM, Steve Baxter wrote:
This has bitten a few people.
The actual problem is that GCC 4 uses the *address* of typeids
when comparing for RTTI rather than the class name that is in
the typeid. This is arguably more efficient, but doesn't work
properly if your code doesn't obey the one definition rule:
http://en.wikipedia.org/wiki/One_Definition_Rule
Unfortunately it is very easy to accidentally not obey the ODR.
Inline code used in plugins will cause RTTI information to be
linked multiple times (once in each plugin). The compiler and
linker will not catch problems here - you have to deal with this
yourself.
To fix the problem:
- Your plugins need to export all their symbols
- If you use CFBundle to load your plugins, it will not do the
right thing. You need to load your plugin with dlopen
( RTLD_GLOBAL ) (you can then load it with CFBundle as well)
- If you are supporting 10.3.9 you have an extra problem - there
is a bug in the C++ runtime which will still prevent RTTI from
working between modules. I hope Apple is going to release a fix
for this at some point (the fix is actually in the 10.3.9 and
10.4u SDKs)
Doing this allows the dynamic linker to merge symbols as each
plugin loads. Each symbol will then be loaded only once and ODR
will be obeyed.
Personally I think it is a complete pain for GCC to have
different behaviour to CodeWarrior and VC++ in this respect.
They have extracted a little bit of performance (comparing the
address of typeids rather than doing a text compare is more
efficient) but caused an awful lot of pain. Apple could fix
this - there is a #define in the C++ runtime to switch back to
string comparisons. Unfortunately with 10.3.9 and upwards, this
is part of the system and Apple are refusing to change it.
Cheers,
Steve.
On 14 Jul 2006, at 22:14, Eric Slosser wrote:
Sam, this is a semi-well-known problem.
GCC decides to give an exception to a handler when the typeinfo
of the exception matches that of the handler (or is a sub-
class). But the comparsion isn't based on the munged name of
the symbol, it's based on the equality of a integer constant
that's handled out by the linker.
So you need to export the typeinfo symbols representing the
exceptions you care about from both the catcher and catchee.
The easiest way to see if this is your problem is to export all
symbols, and don't strip any symbols, and see if the problem
goes away.
If this helps you, thank Marshal Clow for reading your problem
and remembering that I had the same one months ago. Oh, and
Lisa Lippencott and Sean Parent for explaining the answer to me
back then. And the academy. And mom.
See http://www.devworld.apple.com/documentation/Darwin/Reference/
ManPages/man1/gcc.1.html, especially this part:
-fvisibility-ms-compat
This flag attempts to use visibility settings to make
GCC's C++
linkage model compatible with that of Microsoft Visual
Studio.
The flag makes these changes to GCC's linkage model:
1. It sets the default visibility to 'hidden', like -
fvisibil-
ity=hidden. 2. Types, but not their members, are not
hidden by
default. 3. The One Definition Rule is relaxed for
types without
explicit visibility specifications which are defined
in more than
one different shared object: those declarations are
permitted if
they would have been permitted when this option was
not used.
This option is discouraged, rather, it is preferable
for types to
be explicitly exported as desired on a per-class
basis. Unfortu-
nately because Visual Studio can't compare two
different hidden
types as unequal for the purposes of type_info and
exception han-
dling, users are able to write code that relies upon
this behavior.
Among the consequences of these changes are that
static data mem-
bers of the same type with the same name but defined
in different
shared objects will be different, so changing one will
not change
the other; and that pointers to function members
defined in differ-
ent shared objects will not compare equal. When this
flag is
given, it is a violation of the ODR to define types
with the same
name differently.
You can pass this flag manually in the Other C++ Flags build
setting in Xcode 2.3 and later.
Chris
Steve Baxter
Software Development Manager
Improvision
+44-2476-692229
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40apple.com
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40improvision.com
This email sent to email@hidden
Steve Baxter
Software Development Manager
Improvision
+44-2476-692229
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden