SIGSEGV when using dynamic_cast<>

513 views
Skip to first unread message

celavek

unread,
Jul 10, 2012, 6:20:45 AM7/10/12
to andro...@googlegroups.com
Hi all,

I'm getting a SIGSEGV when using dynamic_cast. It's a very simple
executable(code below) that is built using the standalone toolchain and
ran on a Pandaboard with Linaro Android 4.0.3.
According to the documentation the standalone toolchain has exceptions
and rtti enabled by default so I don't use the specific flags. I link against the
shared version of the "gnustl" library and also with "supc++". If I check my
executable with "nm" the dynamic_cast symbol is indeed undefined explaining
the crash.
What am I doing wrong here? Do I need to use some other compiler or linker flags?

Thanks

Compiler flags:
-marm -march=armv7-a -mfloat-abi=softfp -mfpu=neon -Wuninitialized -Wno-psabi -fsigned-char -w -DANDROID -fPIC   -g -Wstrict-aliasing=3 -Wstrict-overflow=3 -D_DEBUG

Linker flags:
-Wl,-nostdlib -Wl,-lgnustl_shared -Wl,-lsupc++  -rdynamic -ldl -lgcc -lc -lm -ldl

Code(corrected example from cppreference.com):

#include <iostream>
#include <typeinfo>

struct V
{
        virtual void f() {};  // must be polymorphic to use runtime-checked dynamic_cast
};

struct A : virtual V {};
struct B : virtual V
{
        B(V* v, A* a)
        {
                // casts during construction
                dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B, results in B*
                dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of B
        }
};

struct D : A, B
{
        D() : B((A*)this, this) { }
};

struct Base
{
        virtual ~Base() {}
};

struct Derived : Base
{
        virtual void name() {}
};

struct Some
{
        virtual ~Some() {}
};

int main()
{
        D d; // the most derived object
        A& a = d; // upcast,dynamic_cast may be used, but unnecessary
        try
        {
                D& new_d = dynamic_cast<D&>(a); // downcast
                B& new_b = dynamic_cast<B&>(a); // sidecast
        }
        catch (const std::bad_cast& e)
        {
                std::cout << "Exception: " << e.what() << std::endl;
        }

        Base* b1 = new Base;
        if(Derived* d = dynamic_cast<Derived*>(b1))
        {
                std::cout << "downcast from b1 to d successful\n";
                d->name(); // safe to call
        }

        Base* b2 = new Derived;
        if(Derived* d = dynamic_cast<Derived*>(b2))
        {
                std::cout <<"downcast from b2 to d successful\n";
                d->name(); // safe to call
        }

        if(Some* d = dynamic_cast<Some*>(b1))
        {
                std::cout << "downcast from b1 to Some successful\n";
        }

        delete b1;
        delete b2;
}

celavek

unread,
Jul 10, 2012, 6:34:13 AM7/10/12
to andro...@googlegroups.com

EDIT to my original post:


"If I check my executable with "nm" the dynamic_cast symbol is indeed undefined explaining
the crash. "

Above statement is somewhat incomplete. I do not find indeed the symbol in the executable although it's
present in the libgnustl_shared.so. What's confusing is that from the documentation I understood
that the rtti and exceptions support is implemented by libsupc++ which is a static one so
linking against my executable should bring all the symbols in.

Pablo Márquez

unread,
Jul 10, 2012, 8:27:36 AM7/10/12
to andro...@googlegroups.com
I had similar problems. The VM failed to load the shared library implementing my native activity because some symbols were missing. I fixed the problem using the compiler switch -Wl,-z,defs, which tells the linker to resolve all symbols. Very useful when working with a standalone toolchain.



Cheers,
Pablo.

--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To view this discussion on the web visit https://groups.google.com/d/msg/android-ndk/-/5q9blYWMEmUJ.

To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to android-ndk...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.



--
....:::::: ^__^ ::::::....

celavek

unread,
Jul 10, 2012, 9:25:57 AM7/10/12
to andro...@googlegroups.com

Thanks for the tip but unfortunately is not working.

David Turner

unread,
Jul 10, 2012, 11:42:27 AM7/10/12
to andro...@googlegroups.com
That doesn't seem to be related to the NDK in any way. Better go to a Linaro-specific forum (after all they provide the toolchain).

--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To view this discussion on the web visit https://groups.google.com/d/msg/android-ndk/-/BmuZqV-x37QJ.

celavek

unread,
Jul 10, 2012, 12:10:41 PM7/10/12
to andro...@googlegroups.com

I guess it's somewhat my bad that I did not provide all the details ...

I'm RUNNING the thing on a Pandaboard with the Linaro Android 4.0.3 image
but I'm using the standalone toolchain from the NDK r8 to build. The gnustl
and the spuc++ libraries are the ones which came with the NDK.

I checked both the gnustl_shared.so and libsupc++ and the symbol for
dynamic_cast is present.
Any hint would be appreciated as I'm kind of stuck on this issue.

David Turner

unread,
Jul 11, 2012, 4:59:19 AM7/11/12
to andro...@googlegroups.com
Nope, this really depends on the order used when specifying the libraries on the link command line, as in:

  -lgnustl_shared -lsupc++

Means first look for symbols in libgnustl_shared.so then libsupc++.a

If the symbol is first found as exported by libgnustl_shared.so, then an import/relocation will be put in the final binary, otherwise, the code from libsupc++.a is copied into your binary instead.

If you do

  -lsupc++ -lgnustl_shared

Any symbol from libsupc++.a that your binary depends on will be copied to your binary.

This may or may not what you need, but libgnustl_shared.so has its own copy of libsupc++.a so I don't think you need -lsupc++ here.

Why are you using -nostdlib anyway? 

--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To view this discussion on the web visit https://groups.google.com/d/msg/android-ndk/-/5q9blYWMEmUJ.

David Turner

unread,
Jul 11, 2012, 4:59:52 AM7/11/12
to andro...@googlegroups.com
Yes, sorry for the confusion. By the way, have you tried linking against libgnustl_static.a instead? 

--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To view this discussion on the web visit https://groups.google.com/d/msg/android-ndk/-/UNAx7l080jcJ.

celavek

unread,
Jul 11, 2012, 7:37:59 AM7/11/12
to andro...@googlegroups.com


On Wednesday, July 11, 2012 10:59:19 AM UTC+2, Digit wrote:


EDIT to my original post:


"If I check my executable with "nm" the dynamic_cast symbol is indeed undefined explaining
the crash. "

Above statement is somewhat incomplete. I do not find indeed the symbol in the executable although it's
present in the libgnustl_shared.so. What's confusing is that from the documentation I understood
that the rtti and exceptions support is implemented by libsupc++ which is a static one so
linking against my executable should bring all the symbols in.


Nope, this really depends on the order used when specifying the libraries on the link command line, as in:

  -lgnustl_shared -lsupc++

Means first look for symbols in libgnustl_shared.so then libsupc++.a

If the symbol is first found as exported by libgnustl_shared.so, then an import/relocation will be put in the final binary, otherwise, the code from libsupc++.a is copied into your binary instead.

If you do

  -lsupc++ -lgnustl_shared

Any symbol from libsupc++.a that your binary depends on will be copied to your binary.

 
That is what I was thinking also but it's not happening like that in my case. In case of ordering like " -lgnustl_shared -lsupc++" there is no
relocation present in the final executable and the symbol is marked as undefined hence the crash; if I build the same source code
for the x86 with the stock GCC on my machine then the relocation section is there as expected. In case of ordering like
"-lsupc++ -lgnustl_shared" there is no copy of the symbols from the archive into the final binary and my binary is exactly in the same
situation as the first case.

I finally managed to work around the issue by forcing the compiler to include the archive in its entirety
"-Wl,--gc-sections -Wl,--whole-archive libsupc++.a -Wl,--no-whole-archive". From what I have tested so far there are no side
effects(not 100% sure it won't happen) and I can use dynamic_cast without any problems. 
 
This may or may not what you need, but libgnustl_shared.so has its own copy of libsupc++.a so I don't think you need -lsupc++ here.

 
The linking fails without the libsupc++.
 
Why are you using -nostdlib anyway? 

To avoid linking with the libstdc++.
 

--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To view this discussion on the web visit https://groups.google.com/d/msg/android-ndk/-/5q9blYWMEmUJ.

To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to android-ndk+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages