4

I'm writing an event-based programming library for use on the BeagleBone Black and have encountered a strange error.

When I compile the exact same code with the exact same flags I receive the following errors on the ARM-based processor, but not when I run the code compiled for my x86 computer.

$ ./missionControl
pure virtual method called
pure virtual method called
pure virtual method called
terminate called recursively
terminate called recursively
Aborted

When I compile and run on my laptop, the program runs correctly.

This is the command I'm using to compile (ish, I'm using a Makefile, but both methods of compilation exhibit precisely the same behavior):

g++ -std=gnu++11 -pthread -O3 -D_GLIBCXX_USE_NANOSLEEP -o missionControl `find . -name *.cpp`

It doesn't matter whether I cross-compile with Ubuntu's arm-linux-gnueabi-g++ or the ARM-compatible g++ on the actual BeagleBone, I still get errors on ARM.

My question is this: What could be causing this error, and what can I do to try to find the source? Why would this happen on one processor architecture, but not another, for the same version of G++?

Thanks!

Here's a backtrace from the ARM processor's GDB:

#0  0xb6d4adf8 in raise () from /lib/libc.so.6
#1  0xb6d4e870 in abort () from /lib/libc.so.6
#2  0xb6f50ab4 in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/libstdc++.so.6
#3  0xb6f4ea4c in ?? () from /usr/lib/libstdc++.so.6
#4  0xb6f4ea4c in ?? () from /usr/lib/libstdc++.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
Alex Reinking
  • 16,724
  • 5
  • 52
  • 86
  • 2
    You probably have an error in managing the lifetime of some polymorphic object or collection of objects. The error typically shows when you attempt to delete something that's already been deleted. – Kerrek SB Nov 15 '13 at 21:02
  • This error is happening right as I start my program, before anything would get deleted (I think)... I'm using smart pointers throughout the program, and valgrind reports no errors and all memory freed by the end of the correctly-running program on x86. – Alex Reinking Nov 15 '13 at 21:08
  • Hm... try and reduce the problem? Remove global variables until it works? Are you sure the error happens *before* `main` is called? – Kerrek SB Nov 15 '13 at 21:10
  • @KerrekSB I'm not sure if it's before main() is called. Let me try to add a `cout` right at the top of main(). The only global variable I have is a mutex in one translation unit, so I'll try to factor that into a class. – Alex Reinking Nov 15 '13 at 21:13
  • Just checked, it definitely enters `main()`, so there shouldn't be a need to play with the global variables, right? – Alex Reinking Nov 15 '13 at 21:21
  • 1
    I have this exact same problem - I guess not many people are using std::thread on a beagleboard huh? – Dave Branton Apr 23 '14 at 01:20

3 Answers3

4

The problem turned out to be due to a bug in the ARM version of libstdc++ that runs on the BeagleBone. A small toy program that has no virtual functions at all causes the same error ("pure virtual function called") when std::thread is created.

I'm going to try to compile a custom version of gcc/libstdc++ 4.8 on the BeagleBone itself -- even if it takes a long time.

Alex Reinking
  • 16,724
  • 5
  • 52
  • 86
  • I ultimately wiped the awful Angstrom linux off of the BeagleBone and replaced it with Ubuntu. Cross compiling works as expected. To anyone using this wonderful device: WIPE it and install Ubuntu instead. – Alex Reinking Apr 22 '14 at 06:40
  • 1
    Did you end up trying to build gcc? Or did you give up on that and just go straight to Ubuntu? – Dave Branton Apr 23 '14 at 01:21
  • I tried to build gcc. The build failed partway through. I wiped it and went to Ubuntu. – Alex Reinking Apr 23 '14 at 05:05
2

The pure virtual method called error occurs when you attempt to use dynamic dispatch to call a function that is pure virtual in a base before the derived type that implements it has been constructed or after it has already destructed.

The most common cause for this is if the base class attempts to call a virtual function that is pure at this level through the constructor or destructor. Other than that, as it has been pointed out in some comments, if you attempt to access a dead object, you might also run into this same issue.

Just attach a debugger to the program and see what virtual function is called and from where.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • Could you provide a hint as to how to use GDB to find this error? If I let it run and crash, the backtrace isn't very helpful. I added a backtrace to my question. – Alex Reinking Nov 15 '13 at 21:31
  • Also, why would this only happen on ARM? The same compiler version emits good code on x86. – Alex Reinking Nov 15 '13 at 21:34
  • I just replaced ALL of the pure virtual functions with regular virtual functions that print the function name and then call `abort()`. I still experience the same problem **and** the error messages I inserted never get printed. – Alex Reinking Nov 15 '13 at 22:07
2

See: https://groups.google.com/forum/#!topic/automatak-dnp3/Jisp_zGhd5I

And: Why does this simple c++11 threading-example fail, when compiled with clang 3.2?

Now, I have no idea why this works, but it does for me at least. Add the following four preprocessor definitions to the compiler command line:

__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8

I haven't experimented to see if they are all required, or whether or not you can get away with only some. But this solved the problem for me. Thanks to those who wrote the above answers, and thanks to my colleague for out-googling me :)

Community
  • 1
  • 1
Dave Branton
  • 494
  • 3
  • 11