React-native: E/libc++abi: terminating with uncaught exception of type std::bad_cast: std::bad_cast

Created on 15 Jul 2020  Â·  15Comments  Â·  Source: facebook/react-native

Description

As of version 0.62.0, there's a conflict in libc++_shared.so between react-native and tesseract. This issue can be observed with any version of ScanbotSDK, however, it only shows up as of 0.62.0 react-native version.

I already faced SDK linking issues with this version of react-native when I first tried it out. Then found that an additional required step is now adding the following to settings.gradle:

include ':react-native-scanbot-sdk'
project(':react-native-scanbot-sdk').projectDir =
        new File(rootProject.projectDir, '../node_modules/react-native-scanbot-sdk/android/app')

But, as I am posting this, it's still not enough. Workaround and details below.

React Native version:

System:
    OS: macOS 10.15.6
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 3.03 GB / 32.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 12.13.0 - ~/.nvm/versions/node/v12.13.0/bin/node
    npm: 6.12.0 - ~/.nvm/versions/node/v12.13.0/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  SDKs:
    iOS SDK:
      Platforms: iOS 13.5, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
    Android SDK:
      API Levels: 26, 28, 29
      Build Tools: 27.0.3, 28.0.3, 29.0.2, 29.0.3
      System Images: android-28 | Google Play Intel x86 Atom
      Android NDK: 21.0.6113669
  IDEs:
    Android Studio: 4.0 AI-193.6911.18.40.6514223
    Xcode: 11.5/11E608c - /usr/bin/xcodebuild
  npmPackages:
    react: 16.11.0 => 16.11.0 
    react-native: 0.62.2 => 0.62.2 
  npmGlobalPackages:
    react-native: 0.61.4

Steps To Reproduce

  1. Clone https://github.com/doo/scanbot-sdk-example-react-native/tree/v4.1.0
  2. Change "react-native-scanbot-sdk": "4.1.0-rc2", back to "react-native-scanbot-sdk": "4.1.0-beta10",
  3. react-native run-android
  4. Press Scan MRZ on ID Card
  5. E/libc++abi: terminating with uncaught exception of type std::bad_cast: std::bad_cast

The same can be reproduced with a hello-world app created via npx react-native init AwesomeProject

Expected Results

Well, I'd expect the MRZ Scanner to start. As you can observe when you change "react-native-scanbot-sdk" back to "4.1.0-rc2", where I've implemented the workaround.

Or you can change "react-native" to anything below "0.62", and it will run as expected.

Snack, code example, screenshot, or link to a repository:

Instead of snacking, I'll explain the process and workaround that I found.

First, the issue. When compiling our core with debug symbols attached, I can see that the bad_cast is, in fact, inside tesseract. In a relatively harmless piece of code, nonetheless:

const char* buffer = "NULL 0 NULL 0\n";
std::istringstream stream(buffer);
stream.imbue(std::locale::classic());
// æ ‡ 1 0,255,0,255,0,0,0,0,0,0 Han 68 0 68 æ ‡  # æ ‡ [6807 ]x
stream >> std::setw(255) >> unichar >> std::hex >> properties >> std::dec;

If I move that same block back into our core, it passes through it with a breeze... but inside tesseract it crashes with the bad_cast exception inside c++ shared library. It cannot find a facet, that should be there in every case.

Well, at this point I was pretty dumbfounded, and cannot debug shared library without debug symbols and with optimizations.

Off to my next adventure: Building the standard library in debug mode. But of course, that cannot be done separately, so I had to download all of Google's monorepo (60gb, woo) and compile the entirety android NDK from source in debug, so I could see what the hell was going on in locale.cpp.

That step was a bit easier than I thought. Just sprinkled some of the following around in different makefiles:

LOCAL_CFLAGS += -O0 -UNDEBUG -g
LOCAL_CPPFLAGS += -O0 -UNDEBUG -g

Now I have the debug build of libc++_shared.so, weighing just shy of 6mb (a bit less than 1mb in release), that I copied to my NDK directory: /Users/$USER/Library/Android/sdk/ndk/19.2.5345600/sources/cxx-stl/llvm-libc++/libs/arm64-v8a

I specifically used the same NDK react-native is compiled with, as described here. And I also built react-native from source, just so I could control every aspect of it and specify which NDK to use in all cases...

And it works. No more crash. Cannot reproduce the issue with the debug build of libc++_shared.so. Well, what now?

So I included the debug build in our SDK and wrote a simple "postinstall" script that copies the binary to project/app/src/main/jniLibs and now the correct c++ standard library is included in the apk.

As you can see, that's still a... well, relatively dirty workaround. Still not sure what exactly changed in react-native builds between versions 0.61 and 0.62 on that level. Anyone?

Thank you for coming to my TED talk

React Native Team Attention

Most helpful comment

Hi,
Any expected date to fix this issue? How can we get the React-Native team to respond? The proposed "workarounds" are not acceptable. We need a fix!!
This issue was opened on July 15 and I have yet to see any response from the react team....

All 15 comments

We're experiencing a similar crash in our app after upgrading React Native from 0.61.5 to 0.63.2. While we are not using tesseract, we have our own C++ libraries which have worked fine before. After updating, we are experiencing a std::bad_cast exception in the yaml-cpp library originating from this line, which also uses a basic stringstream operation. In lldb I could verify that key is a valid, null-terminated char array, so the error appears to originate from the standard library itself. The problem persisted after linking against React Native's NDK version (19.2.5345600).
Interestingly, we were able to 'resolve' the issue by also statically linking our library against the stl (setting the CMake parameter ANDROID_STL=c++_static), after which no exception is thrown and our code appears to run as expected. We have yet to test on a device outside of the simulator.
Could the libc++_shared.so be broken somehow?

I am also facing the same issue on 0.62 and above. Although it seems to be working on 0.61.5 as commented above. I am using an android library which also contains the native libC++_shared.so. I have also checked with the latest NDK, but that does not solve the issue with 0.62 and above.

Waiting for a solution on this.

Hi,
Also experiencing similar issues. Using std such as stringstream stopped working, and causing crashes.
It was working fine when using 0.61.
Hoping to get this fixed.
Thank you.

Any update about this issue?
I get the same issue with "react-native": "0.62.2", anyone can help me resolve this issue?
Thank you!

@Nikituh Can you share your script, file and steps to fix this issue at the moment?

FYI, I can confirm that for us statically linking against the STL (e.g. by passing the CMake parameter ANDROID_STL=c++_static) solved the issue for us in simulator and on-device.

@TheLartians Can you give me more detail? I mean steps to do it to resolve this issue. Thank you

Sure, though I'm not sure if this will be of much use to you, as we fixed the issue for our own self-maintained C++ library and don't use tesseract or derived projects. We simply added the following line to the gradle script, which is responsible for calling CMake.

    externalNativeBuild {
      cmake {
        arguments.add("-DCMAKE_BUILD_TYPE=Release")
+       arguments.add("-DANDROID_STL=c++_static")
        targets.add("path/to/CMake/project")
      }
    }

By statically linking against the STD, our library will not use the libc++_shared.so that is used by React Native, which fixed the crash for us. I guess a similar patch could temporarily fix tesseract as well, but I don't really know how it's built for React Native.

@TheLartians Thank you, I had to try it, it's no more crash but the app always reopens and not work as well. I think I'll downgrade to RN 0.61 and waiting for RN fix this problem!

@minhchienwikipedia I wouldn't count on the RN team addressing this issue any time soon. Not because I do not have faith in them, but simply because it's very difficult to even diagnose what exactly is causing this issue. My best guess is it'll happen when they upgrade the NDK.

Anyway, everything I did, with the jnilibs directory and custom libc++_shared.so build, is openly available within the package: https://www.npmjs.com/package/react-native-scanbot-sdk 😄

@Nikituh I resolved this issue by custom libc++_shared.so, thank you so much :D

Having the same problem with react-native 0.62.0 AND 0.63.2

This issue is preventing me upgrading from 0.61, and unfortunately none of the mentioned workarounds are of use as a 3rd party library is providing their own libc++_shared.so

It seems to be a problem caused by the flipper library, and the restoration of the 0.61.0 flipper integration method seems to take effect
If it goes back to 0.61.0, it seems that the picture is not rendered on ios 14.x devices?

Hi,
Any expected date to fix this issue? How can we get the React-Native team to respond? The proposed "workarounds" are not acceptable. We need a fix!!
This issue was opened on July 15 and I have yet to see any response from the react team....

Was this page helpful?
0 / 5 - 0 ratings