1

I'm experiencing a very weird behaviour. Was unable to isolate the problem in a MCVE, but will when I'll progress on my investigation.

I have a program, based on CPPUNIT library and Qt that runs ~900 unit tests. This program is deployed on Android using QtCreator. It links with ~80 libraries, each one defining some tests.

On PC, the programs runs perfectly. When deployed on Android, when I run it, after some tests were ran (~100), I start getting std::bad_cast exceptions for every dynamic_castdone within my tests. I see it comes from places where I call dynamic_cast on a pointer, not on a reference. According to the doc, std::bad_cast is only thrown when dynamic_cast is called on a reference...

void validate( ParentTestHelper& testHelper )
{
    const ChildTestHelper* child = dynamic_cast<const ChildTestHelper*>( &testHelper );
    ...
}

However, my code throws std::bad_cast.

If I run only the test doing the dynamic_cast, it works. It will only fail if it is run after other ones...and running them manually one by one does not let me reproduce the problem. There must be something weird somewhere leading to this issue and I'm still investigating.

If anyone has an idea why dynamic_cast called on a pointer could throw std::bad_cast, this may help...

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
jpo38
  • 20,821
  • 10
  • 70
  • 151
  • 2
    This cannot happen in standard C++. Either your implementation has a bug (not terrible likely, but can happen), or your tests are broken in some way. – Baum mit Augen Aug 23 '17 at 15:35
  • Since you are targeting Android, have you tried switching to [other runtimes](https://developer.android.com/ndk/guides/cpp-support.html) and see if that's the problem? – kennytm Aug 23 '17 at 15:36
  • @BaummitAugen: Hopefully I'll find out what's wrong and will be able to answer my own question. Possibly a third party library does a dynamic_cast on a reference and does not catch the exception.... – jpo38 Aug 23 '17 at 16:21
  • With regards to your question, `dynamic_cast` won't throw casting to a pointer. But to help you more, you have to provide relevant details, such as how do you know the `std::bad_cast` was thrown from the lines you say, the ones with `dynamic_cast` to pointers? because I have trouble believing there is an implementation so bad it would do that – TheCppZoo Aug 23 '17 at 16:21
  • @kennytm: Not sure this would be doable from QtCreator. I let him compile and deploy, I don't use ndk build system directly – jpo38 Aug 23 '17 at 16:22
  • @jpo38 Now that should be easy to find out by just looking at the backtrace. – Baum mit Augen Aug 23 '17 at 16:22
  • @EdMaster: Undefined behaviour is a nice idea....hopefully I will be able to isolate the problem and find out what's wrong... – jpo38 Aug 23 '17 at 16:23
  • @BaummitAugen: Unfortunately, I can only run those tests in Release (they take hours to run), so I only have very limited debugging information available. – jpo38 Aug 23 '17 at 16:28
  • Possibly it is low on some resource it needs for the dynamic cast, or some of the internal data is corrupted. What happens if you only run some of the tests (say, half of 3/4) before the one that fails? – 1201ProgramAlarm Aug 23 '17 at 16:37
  • @1201ProgramAlarm: I'll try to disable tests one by one untill it starts working and see. But it takes our as the test suite takes more than 3 hours to run... – jpo38 Aug 23 '17 at 16:41
  • 2
    According to https://developer.android.com/ndk/downloads/revision_history.html, there is a known issue with NDK r11 that "*The combination of Clang, x86, stlport_static, and optimization levels higher than `-O0` causes test failures with dynamic_cast.*" Does your testing environment match the condition? This has been fixed in r12, and the latest version r15c BTW. – kennytm Aug 23 '17 at 16:50
  • @kennytm: I'm running on armv7. But as I'm using r11b, that's definitely suspicious.... – jpo38 Aug 24 '17 at 06:24

1 Answers1

0

After a lot of investigations, I found out that the root cause of the problem was the fact that I applied a custom facet to std::cout. At some point, it makes boost code throw std::bad_cast while doing a use_facet in it's boost::posix_time::ptime's operator<<.

See this other topic where hopefully someone will explain why: Why imbue with boost::posix_time::time_facet on std::cout crashs my app?

jpo38
  • 20,821
  • 10
  • 70
  • 151