Re: How is this not a complier error? (dynamic casting problem)
Re: How is this not a complier error? (dynamic casting problem)
- Subject: Re: How is this not a complier error? (dynamic casting problem)
- From: Andreas Grosam <email@hidden>
- Date: Wed, 27 Jul 2005 11:41:38 +0200
On 26.07.2005, at 18:55, Zachary Pincus wrote:
Andreas, Thanks for your help!
I've got some more details about my dynamic-downcast problem.
First, the problem disappears when I switch to gcc3.3 with gcc_select.
Firstly, i need to mention that there is a certain likelyhood that
there is actually a problem with the dynamic_cast operator in gcc-4!!
In another thread in this list, "Problem with dynamic_cast & exceptions
using GCC 4?", Jesper Papmehl described another problem, that - at the
first glance - is apparently a "symbol visibility" problem. However, it
turned out - it is not! It actually is a problem with the dynamic cast
operator. He already filed a bug to Apple.
Please let me describe what he has dicovered in brief:
std::exception* ep1 = new logic_error("");
std::exception* ep2 = new invalid_argument("");
assert(dynamic_cast<std::logic_error*>(ep1)); // OK
assert(dynamic_cast<std::invalid_argument*>(ep2)); // FAILED!!
That is, for some strange reason, the second down_cast does not work.
This only does not work when trying to down_cast
"std::invalid_argument", other exception types do work.
I already checked, that the stdlibc++ exports runtime information for
std exception classes and especially for std::invalid_argument.
K, back to your problem.
Second, you are right to wonder if the problem has to do with DSO
boundaries. My attempts to make complete test cases (as you suggest
below) did not re-create the bug. In fact, I *only* see the error if
the Image object was passed across a DSO boundary. If I make a new one
in situ, no error.
If you define a class which later may be an operand in a dynamic_cast
operator which is called from within another DSO - or if this is a
class which is thrown in an exception and the catch expression is in
another DSO or crosses DSOs, you should (need to) export RTTI symbols.
RTTI will be exported only when the class is exported (gcc-4.0.0). (see
below how to ensure to export the class).
Now, I'm fairly sure that the RTTI information is being exported. I
don't think I've any of the "symbols hidden by default" flags on.
Moreover, the RTTI information seems to exist for the Image object
that can't be properly downcast, since I can call typeid and get the
correct name for the pointed-to object.
Well, now since there might be a problem with the dynamic_cast
operator, you really need to double check your problem and verify if
your problem is really a dynamic_cast problem. If so, we have a serious
defect in gcc-4, and i really would appreciate if this get more
attention from the folks at Apple.
Is there a better run-time check to make sure that the RTTI
information was properly exported?
hm, typeid may access the mangled name of the type, which would be not
there if RTTI is not there.
You can also use the nm tool, to check which symbols have been
exported. For gcc-4 RTTI symbols start with _ZTI.
Please read the man page for nm and make some tests with small sources.
In order to be sure that a class will be exported, I recommend to use
macros which explicitly define the visibility attribute. So, in order
to be sure to export a certain class you would write:
class EXPORT MyClass
{
// ...
};
The macro EXPORT expands to the visibility attribute - if this is
supported by the compiler:
#if ...
#define EXPORT __attribute__ ((visibility("default")))
#else
In another mail, I already described how to define these macros.
Also, how do I force this information to be exported -- just declare
a class "extern"?
For gcc-4: no. For gcc-4 you need to use the visibility attribute in
the class definition:
class __attribute__ ((visibility("default"))) MyClass
{
public:
virtual ...
// ...
};
Then, the class is always exported, no matter which compiler options
are set.
For gcc-3.3, you need no visibility attribute, all symbols (classes)
are exported from the compiler:
class MyClass
{
public:
virtual ...
// ...
};
(Note, for gcc-3 you can use an "exported symbols file" to limit the
exported symbols - but its usage is cumbersome - to be politely.)
For more information, please read:
<http://developer.apple.com/documentation/DeveloperTools/Conceptual/
CppRuntimeEnv/Articles/SymbolVisibility.html>
see also
<http://gcc.gnu.org/wiki/Visibility>
In case there is some hidden interaction causing symbols not to be
exported by default, I'd like to see if forcing them to be exported
works.
Note, per default the compiler exports all symbols.
However, XCode (or you) may set build settings which override the
compiler defaults - which causes XCode to emit compiler options.
There are two compiler options which control symbol visibility:
-fvisibilty= hidden | default
-fvisibility-inlines-hidden
In XCode the corresponding build settings are:
Symbols Hidden by Default
Inline Functions Hidden
If you check "Symbols Hidden by Default" in the build setttings, XCode
emits "-fvisibilty=hidden" as a compiler option.
Likewise, if you check "Inline Functions Hidden", XCode emits
"-fvisibility-inlines-hidden".
Now, I'm combing through the exact GCC flags that the project is
actually compiled with, but I see nothing suspicious. Also, the fact
that changing to gcc3.3 without changing any other settings makes
things work all of a sudden worries me -- do gcc3.3 and gcc4.0 differ
in how they handle exported symbols?
Yes - although the compiler defaults yield to the same behavior. This
will be explained in detail in the documentation.
Regards
Andreas
Thanks,
Zach Pincus
Program in Biomedical Informatics and Department of Biochemistry
Stanford University School of Medicine
On Jul 26, 2005, at 4:28 AM, Andreas Grosam wrote:
On 26.07.2005, at 03:45, Zachary Pincus wrote:
Hello,
I'm running into a problem in my C++ code (which uses RTTI and
dynamic_cast) which I can only account to be a g++ compiler error.
snip
the result of the downcast looks strange.
Can you test whether a dynamic downcast is successful using these
classes:
template <int K>
class base
{
public:
enum { value = K };
virtual ~base() {}
};
template <typename T, int K>
struct derived : base<K>
{
derived(const T& v = T()) : x(v) {}
T x;
};
On XCode 1.5 (gcc-3.3) and XCode 2.1 (gcc-4.0.0), the dynamic_cast
works as expected.
Adding a namespace, does not break it, too.
So, one oddity I notice is that the run-time type of the
dereferenced pointers is NOT const, even though it should be.
It seems, the mangled names do not contain a qualifier for non
pointer types, that is:
typeid(const T).name() is_equal typeid(T).name()
typeid(volatile T).name() is_equal typeid(T).name()
where T is a non-pointer type.
This condition evaluates to true also:
( typeid(T) == typeid(const T) )
IMO, this treatment is questionable.
That does not mean, that the compiler is unable to distinguish this
types, though.
But I see no reason that imageBaseP, which points to an itk::Image
object, couldn't be down-cast to the same! Any thoughts?
IMO, the downcast should work.
The base class needs to be a polymorphic class of course, the
compiler would complain otherwise.
The types need to be complete, that means, include everything
necessary to instantiate a complete object. But i guess, the compiler
would also complain, otherwise.
Are the objects instantiated in the same library (DSO)? Is the call
to operator dynamic_cast in the same DSO?
If "No", you need to ensure that RTTI information is exported accross
DSOs - means your types (template classes) shall be exported.
hm, no more thoughts.
Andreas
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
email@hidden
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:
This email sent to email@hidden