Skip to content

E/libc++abi: terminating with uncaught exception of type std::bad_cast: std::bad_cast #29377

Closed
@Nikituh

Description

@Nikituh

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

Activity

changed the title [-]`E/libc++abi: terminating with uncaught exception of type std::bad_cast: std::bad_cast`[/-] [+]E/libc++abi: terminating with uncaught exception of type std::bad_cast: std::bad_cast[/+] on Jul 15, 2020
TheLartians

TheLartians commented on Aug 14, 2020

@TheLartians

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?

vikramuqudo

vikramuqudo commented on Sep 25, 2020

@vikramuqudo

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.

lendvir

lendvir commented on Sep 26, 2020

@lendvir

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.

minhchienwikipedia

minhchienwikipedia commented on Sep 29, 2020

@minhchienwikipedia

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!

minhchienwikipedia

minhchienwikipedia commented on Sep 29, 2020

@minhchienwikipedia

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

TheLartians

TheLartians commented on Sep 29, 2020

@TheLartians

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.

minhchienwikipedia

minhchienwikipedia commented on Sep 29, 2020

@minhchienwikipedia

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

TheLartians

TheLartians commented on Sep 29, 2020

@TheLartians

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.

minhchienwikipedia

minhchienwikipedia commented on Sep 30, 2020

@minhchienwikipedia

@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!

24 remaining items

Kudo

Kudo commented on May 25, 2021

@Kudo
Contributor

The problem may come from conflict version of libc++_shared.so (between r20 and r21)

scanbot sdk bundled libc++_shared.so with ndk r21.
checked from the sdk 1.70.1 here

react native 0.62/0.63 bundled with ndk r20

some suggestion to add packagingOptions.pickFirst in build.gradle, but the reality is that which libc++_shared.so to be picked is uncertain.
that's why i proposed to remove packagingOptions.pickFirst in react native template after 0.63.

even as far as i know, ndk maintains ABI stability well between updates.
don't know what happened between ndk r20 and r21.
the formal solution might be to build react native from source with ndk r21 + pickFirst (assuming scanbot sdk cannot build from source).
but if what @Nikituh mention that react native 0.64 fixed the problem, maybe ndk fixed the compatibility issue after r20b (react native 0.64 bump ndk to r20b)

Zshay2203

Zshay2203 commented on Jun 2, 2021

@Zshay2203

Hi,

In the past weeks, I tried to investigate the issue, and apparently, the only solution for it (unless Facebook solves the issue before) is to build your native code using the static version of libc++.

In addition, I kept looking for workarounds, and today I found a one, which some of you (including me) will call dirty or nasty - but it works.
I am sharing it with you so can provide your opinions on it (and maybe use it too...), and MORE: explain why it works and whether it could affect RN's functionality:

In the method onCreate() of the RN's class MainApplication.java was changed so its first action is loading libc++_shared.so to the app's memory before any other library RN's code loads:

From:

@Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
    initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
  }

To:

@Override
  public void onCreate() {
    System.loadLibrary("c++_shared");
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
    initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
  }

The reason I took the liberty to make this change is that this class must change whenever a Native module is added to the RN class (See RN's documentation https://reactnative.dev/docs/0.61/native-modules-android#register-the-module) ...

In order to test the change, I used two examples:

  1. The sample code that fails, which is included in the issue's description (with some minor adaptations...) -
    (Verified that the substring "NULL" from buffer is no successfully assigned to unichar)
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;
  1. A conversion from a string to a number, which failed In my company's code:
std::string in_str_ = "1234"; 
   double out_number_ = 0.0;
   std::istringstream iss(in_str_);
   iss >> out_number_;

Thanks
Shay

Zshay2203

Zshay2203 commented on Jun 6, 2021

@Zshay2203

Hi @Kudo,

Last week I found a workaround to the above failure - by explicitly loading libc++_shared.so before RN loads its own Native Shared Libraries.
This change does not require any other change and was verified on different RN apps.

If the issue is still relevant for you, I will be more than happy to have your comments on it.
Thanks
Shay

murtazabeans

murtazabeans commented on Jun 9, 2021

@murtazabeans

@Zshay2203 , you're a rockstar. Though I am still struggling to figure out the future impacts with react native after applying this fix. Do you have any updates on this?

Zshay2203

Zshay2203 commented on Jun 10, 2021

@Zshay2203

@Zshay2203 , you're a rockstar. Though I am still struggling to figure out the future impacts with react native after applying this fix. Do you have any updates on this?

@murtazabeans, You've got me, I am actually Elvis Presley ...
Thanks for the compliment!

Regarding your question, a couple of customers of the company I am working for have applied the workaround in their app without any side effects.

Thinking logically, I really don't think this fix should have any side effect on RN's functionality for the following reasons:

  1. As stated in the issue's description, a call to a steam's ">>" operator fails due to a missing facet. Using Android
    Studio's debugger, I reached the point of failure: Attempt to read an invalid value, which is stored in _Facet::id -
    in the file: __locale under /sources/cxx-stl/llvm-libc++/include:
template <class _Facet>
inline _LIBCPP_INLINE_VISIBILITY
const _Facet&
use_facet(const locale& __l)
{
    return static_cast<const _Facet&>(*__l.use_facet(_Facet::id));
}

My 100% guess is that RN's c++ code sets a locale with it starts when it does not have a specific value, and probably deallocates but its reference is stored in _Facet::id.

  1. Since the failure lies deep inside a commonly used C++ STL code and ONLY the C++ of RN Bridges is affected by it and not a C++ code of RN then I can conclude that RN does not use it at all.

It would be great if one of RN's developers could comment on that.

thanks again
Shay

murtazabeans

murtazabeans commented on Jun 10, 2021

@murtazabeans

@Zshay2203 , I think react native team should update the NDK. Currently the ndk used by react native is 20.1.5948944 which is marked as Unsupported type. It will resolve the problem if the ndk is updated sometime in future.

I have opened a bug on their team for this - #31701

abarbeitohub

abarbeitohub commented on Jun 11, 2021

@abarbeitohub

Here still waiting for the fix from RN. I have issue with amazon-chime-sdk

github-actions

github-actions commented on Jun 1, 2023

@github-actions

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

added
StaleThere has been a lack of activity on this issue and it may be closed soon.
on Jun 1, 2023
github-actions

github-actions commented on Jun 8, 2023

@github-actions

This issue was closed because it has been stalled for 7 days with no activity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @Kudo@dulmandakh@cmario@ph-teven@TheLartians

        Issue actions

          E/libc++abi: terminating with uncaught exception of type std::bad_cast: std::bad_cast · Issue #29377 · facebook/react-native