【问题标题】:SIGSEGV on OpenCV JNI from Android来自 Android 的 OpenCV JNI 上的 SIGSEGV
【发布时间】:2016-09-22 19:22:50
【问题描述】:

我正在尝试通过 OpenCV Java 运行一段代码,然后将 Mat 对象传递给 OpenCV JNI 代码,该代码对其进行 Canny Edge 检测并返回 Mat。但不知何故,当应用程序启动时,我反复收到一个 SIGSEGV,我不确定这是为什么:

09-23 00:30:19.501 20399-20547/com.example.opencv.opencvtest A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x3 in tid 20547 (Thread-7450)

有问题的 Java 代码段是:

@Override
public void onCameraViewStarted(int width, int height) {
    // Everything initialized 
    mGray = new Mat(height, width, CvType.CV_8UC4);
    mGauss = new Mat(height, width, CvType.CV_8UC4);
    mCanny = new Mat(height, width, CvType.CV_8UC4);
}    

@Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
    mGray = inputFrame.rgba();
    Imgproc.GaussianBlur(mGray, mGauss, new Size(), 5);

    // This works perfectly fine
    // Imgproc.Canny(mGauss, mCanny, 0, 20);

    // But this causes a SIGSEGV
    nativeCanny(mGauss.getNativeObjAddr(), mCanny.getNativeObjAddr());
    return mCanny;
}

JNI 代码是:

 extern "C" {
 JNIEXPORT jboolean JNICALL
 Java_com_example_opencv_opencvtest_MainActivity_nativeCanny(JNIEnv *env, jobject instance, long iAddr, long oAddr) {

    cv::Mat* blur = (cv::Mat*) iAddr;
    cv::Mat* canny = (cv::Mat*) oAddr;

    // This line is causing the SIGSEGV because if I comment it, 
    // everything works (but Mat* canny is empty so shows up black screen)
    Canny(*blur, *canny, 10, 30, 3 );

    return true;
  }
}

知道为什么会这样吗?我花了大半天的时间试图弄清楚为什么会出现这种情况,但除了隔离有问题的陈述之外没有取得任何进展。

编辑:来自 cmets

我认为这是 mCanny 的初始化错误。如果我将 JNI 调用更改为 Canny(*blur, *blur, 10, 30, 3 );然后在 Java 中返回 mGauss 而不是 mCanny 那么它工作正常。这暂时解决了它,但老实说我仍然不确定为什么 mCanny 会导致 SIGSEGV。

【问题讨论】:

  • 应该在 sigsegv 错误消息之后以逻辑方式打印堆栈跟踪。尝试将 logcat 上的过滤器更改为“无过滤器”,如果您在输出中看到堆栈跟踪,请告诉我们。
  • 追踪是:09-23 01:45:32.911 44​​2-442/? I/DEBUG:回溯:09-23 01:45:32.911 44​​2-442/? I/DEBUG: #00 pc 00008230 /data/app/com.example.opencv.opencvtest-2/lib/arm/libgauss.so (Java_navin_tuts_opencv_opencvtest_MainActivity_nativeCanny+39) 09-23 01:45:32.911 44​​2-442/? I/DEBUG: #01 pc 0001082b /data/data/com.example.opencv.opencvtest/cache/slice-slice_4-classes.dex 第 39 行是 blur = (cv::Mat*) iAddr;如上所示的行

标签: android c++ opencv android-ndk java-native-interface


【解决方案1】:

SEGV 表示您试图读/写未分配的内存。错误地址是 3。接近 0 的东西几乎总是意味着您取消了对空指针的引用。我的猜测是 mGauss 或 mCanny 的原生对象地址为 0。

【讨论】:

  • 使用调试器检查了这些值,它们显示 -1420884552 和 -1420884432 。这是否意味着它们得到了垃圾值?
  • 这些似乎都不坏-它可能在您的 C 代码中更进一步。不过,在 C 中取消引用 null 的事实是非常确定的。
  • 我认为是 mCanny 初始化出错。如果我将 JNI 调用更改为 Canny(*blur, *blur, 10, 30, 3 );然后在 Java 中返回 mGauss 而不是 mCanny 那么它工作正常。这暂时解决了它,但老实说我仍然不确定为什么 mCanny 会导致 SIGSEGV!
  • @navinpai 老实说,我仍然不确定为什么 mCanny 会导致 SIGSEGV! 如果您发布整个堆栈跟踪,这可能会提供一些线索。例如,如果您在堆栈跟踪中看到 freemalloc(或 newdeleterealloccalloc 等),那么您可能已经以某种方式损坏了堆。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-28
  • 1970-01-01
  • 2013-05-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多