Fatal signal 11 (SIGSEGV) at 0x00000014 (code=1), thread 29925 (cloud.diversion)

本文介绍了一个常见的Android WebView使用过程中遇到的问题——出现SIGSEGV信号导致崩溃,并提供了解决方案,即通过禁用hardwareAccelerated硬加速来避免此问题。

android使用webView产生 Fatal signal 11 (SIGSEGV) at 0x00000014 (code=1), thread 29925 (cloud.diversion)奔溃问题解决办法。

android 使用hardwareAccelerated(硬加速)有可能会导致这样的问题。webView禁用掉就可以了。

如:myWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); 

### 修复 Android JNI 中 `while` 循环刷新 Surface 导致的 `SIGSEGV` 错误 在 Android 的 JNI 开发中,使用 `while` 徢环不断刷新数据并更新到 `Surface` 是常见的需求,例如在实时渲染或图像处理中。然而,不当的实现可能导致严重的运行时错误,如 `Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)`,即段错误,通常表示访问了未映射的内存地址。 #### 1. 检查 `ANativeWindow` 是否为空或已被释放 在 `while` 循环中访问 `ANativeWindow` 时,必须确保其不为空且未被释放。如果在 `Surface` 销毁后仍然尝试绘制,将导致非法内存访问。 ```cpp while (isRunning) { if (window == nullptr) continue; ANativeWindow_Buffer buffer; if (ANativeWindow_lock(window, &buffer, nullptr) == 0) { // 更新帧数据 ANativeWindow_unlockAndPost(window); } } ``` 在 `Surface` 被销毁时(如调用 `surfaceDestroyed`),应立即释放 `ANativeWindow` 并终止线程。 #### 2. 确保线程安全和同步机制 JNI 中的渲染线程与 Java 层的 UI 线程是分离的,必须确保线程间的数据访问是同步的。例如,当 `Surface` 被销毁时,应通过标志位 `isRunning` 通知渲染线程退出循环,避免访问已释放的资源[^2]。 ```cpp bool isRunning = false; extern "C" JNIEXPORT void JNICALL Java_edu_example_NativeRenderer_stopRendering(JNIEnv* env, jobject /* this */) { isRunning = false; if (window) { ANativeWindow_release(window); window = nullptr; } } ``` #### 3. 使用 `Handler` 或主线程调用 JNI 方法 如果某些 JNI 方法需要操作 UI 或 `Surface`,应通过 `Handler` 在主线程中调用,避免在子线程中直接操作 `Surface`,否则可能因线程调度不一致导致内存访问异常。 ```java new Handler(Looper.getMainLooper()).post(() -> { startRendering(holder); }); ``` #### 4. 检查权限问题 某些操作(如从 SD 卡读取图像数据)可能需要动态权限申请。如果应用未请求 `READ_EXTERNAL_STORAGE` 或 `WRITE_EXTERNAL_STORAGE`,可能导致访问非法内存地址而崩溃[^1]。 ```java if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1); } ``` #### 5. 使用 `addr2line` 定位崩溃地址 当发生 `SIGSEGV` 错误时,可通过 `addr2line` 工具定位具体出错的代码位置,帮助排查非法内存访问问题[^4]。 ```bash arm-linux-androideabi-addr2line -C -f -e libnative-lib.so 00026877 ``` #### 6. 避免资源竞争和重复释放 确保 `ANativeWindow_fromSurface` 和 `ANativeWindow_release` 成对调用,防止重复释放或多次绑定同一个 `Surface`,这可能导致内存访问冲突。 --- ### 示例代码:修复后的 JNI 渲染线程逻辑 ```cpp #include <jni.h> #include <android/native_window.h> #include <android/native_window_jni.h> #include <pthread.h> #include <unistd.h> ANativeWindow* window = nullptr; bool isRunning = false; void* renderThread(void*) { while (isRunning) { if (window == nullptr) { usleep(10000); // 等待Surface可用 continue; } ANativeWindow_Buffer buffer; if (ANativeWindow_lock(window, &buffer, nullptr) == 0) { // 填充像素数据 uint32_t* pixels = static_cast<uint32_t*>(buffer.bits); int pixelCount = buffer.width * buffer.height; for (int i = 0; i < pixelCount; ++i) { pixels[i] = 0xFF00FF00; // 绿色 } ANativeWindow_unlockAndPost(window); } else { // 锁定失败,短暂休眠避免CPU占用过高 usleep(10000); } usleep(33000); // 控制帧率 } return nullptr; } extern "C" JNIEXPORT void JNICALL Java_edu_example_NativeRenderer_startRendering(JNIEnv* env, jobject /* this */, jobject surface) { if (window != nullptr) { ANativeWindow_release(window); } window = ANativeWindow_fromSurface(env, surface); isRunning = true; pthread_t thread; pthread_create(&thread, nullptr, renderThread, nullptr); } extern "C" JNIEXPORT void JNICALL Java_edu_example_NativeRenderer_stopRendering(JNIEnv* /* env */, jobject /* this */) { isRunning = false; if (window) { ANativeWindow_release(window); window = nullptr; } } ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值