非常难缠的signal 11 (SIGSEGV)

本文深入探讨了在使用Box2D Extension时遇到段错误问题的常见场景及解决方法,包括避免频繁的大规模body操作、合理管理线程、优化Contact Listener设计、采用队列管理body生命周期等策略,旨在帮助开发者有效预防和解决此类问题。
现在很多游戏都是动态模拟物理效果的,而事实证明这样的游戏也相当受欢迎。。。。好吧,又是愤怒的小鸟。。。
好吧,Android能实现的,估计也只有Box2D了。。。
最近解决了一个非常恶心难缠的问题,都快被它给逼疯了~见log

10-28 12:39:17.779: I/DEBUG(7749): Build fingerprint: 'google/passion/passion:2.3.6/GRK39F/189904:user/release-keys'
10-28 12:39:17.779: I/DEBUG(7749): pid: 17414, tid: 17446 >>> com.soybea.rocket <<<
10-28 12:39:17.779: I/DEBUG(7749): [color=red]signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad[/color]
10-28 12:39:17.779: I/DEBUG(7749): r0 00000027 r1 deadbaad r2 a0000000 r3 00000000
10-28 12:39:17.779: I/DEBUG(7749): r4 00000001 r5 00000000 r6 44bc8c10 r7 44984e64
10-28 12:39:17.779: I/DEBUG(7749): r8 44bc8b70 r9 44984e54 10 44984e3c fp 800a5368
10-28 12:39:17.779: I/DEBUG(7749): ip afd46668 sp 44bc8ae0 lr afd191d9 pc afd15ca4 cpsr 60000030
10-28 12:39:17.779: I/DEBUG(7749): d0 646f423262287964 d1 6f42796f72747365
10-28 12:39:17.779: I/DEBUG(7749): d2 646e412f65737062 d3 6850656e69676e32
10-28 12:39:17.779: I/DEBUG(7749): d4 786f427363697379 d5 736e657478454432
10-28 12:39:17.779: I/DEBUG(7749): d6 2f696e6a2f6e6f69 d7 79442f4432786f42
10-28 12:39:17.779: I/DEBUG(7749): d8 42ce94f34e6e6b28 d9 3c8888893c888888
10-28 12:39:17.779: I/DEBUG(7749): d10 c26f7c303f800000 d11 3fed9bafc26f7e0e
10-28 12:39:17.779: I/DEBUG(7749): d12 0000000000000000 d13 0000000000000000
10-28 12:39:17.779: I/DEBUG(7749): d14 0000000000000000 d15 0000000000000000
10-28 12:39:17.779: I/DEBUG(7749): d16 3ef18d523ae9735c d17 3fca68bfcfa2d635
10-28 12:39:17.779: I/DEBUG(7749): d18 bf29fd09783e4216 d19 3ec6cd878c3b46a7
10-28 12:39:17.779: I/DEBUG(7749): d20 3f826164f3f641b5 d21 3f5e8ec8e86d933e
10-28 12:39:17.779: I/DEBUG(7749): d22 3e3782e7e0000000 d23 3e33401660000000
10-28 12:39:17.779: I/DEBUG(7749): d24 3fca99a880000000 d25 bfca99a880000000
10-28 12:39:17.779: I/DEBUG(7749): d26 be3ff77520000000 d27 3ef99342e0ee5069
10-28 12:39:17.779: I/DEBUG(7749): d28 bfa2b4442c6a6c2f d29 0000000000000000
10-28 12:39:17.779: I/DEBUG(7749): d30 0000000000000000 d31 0000000000000000
10-28 12:39:17.779: I/DEBUG(7749): scr 80000012
10-28 12:39:17.829: I/DEBUG(7749): #00 pc 00015ca4 /system/lib/libc.so
10-28 12:39:17.829: I/DEBUG(7749): #01 pc 0001c92c /system/lib/libc.so
10-28 12:39:17.829: I/DEBUG(7749): #02 pc 00026504 /data/data/com.soybea.rocket/lib/libandenginephysicsbox2dextension.so
10-28 12:39:17.829: I/DEBUG(7749): #03 pc 00013e18 /data/data/com.soybea.rocket/lib/libandenginephysicsbox2dextension.so
10-28 12:39:17.829: I/DEBUG(7749): #04 pc 00017e34 /system/lib/libdvm.so
10-28 12:39:17.829: I/DEBUG(7749): code around pc:
10-28 12:39:17.829: I/DEBUG(7749): afd15c84 2c006824 e028d1fb b13368db c064f8df
10-28 12:39:17.829: I/DEBUG(7749): afd15c94 44fc2401 4000f8cc 49124798 25002027
10-28 12:39:17.829: I/DEBUG(7749): afd15ca4 f7f57008 2106ec7c edd8f7f6 460aa901
10-28 12:39:17.829: I/DEBUG(7749): afd15cb4 f04f2006 95015380 95029303 e93ef7f6
10-28 12:39:17.829: I/DEBUG(7749): afd15cc4 462aa905 f7f62002 f7f5e94a 2106ec68
10-28 12:39:17.829: I/DEBUG(7749): code around lr:
10-28 12:39:17.829: I/DEBUG(7749): afd191b8 4a0e4b0d e92d447b 589c41f0 26004680
10-28 12:39:17.829: I/DEBUG(7749): afd191c8 686768a5 f9b5e006 b113300c 47c04628
10-28 12:39:17.829: I/DEBUG(7749): afd191d8 35544306 37fff117 6824d5f5 d1ef2c00
10-28 12:39:17.829: I/DEBUG(7749): afd191e8 e8bd4630 bf0081f0 00028344 ffffff88
10-28 12:39:17.829: I/DEBUG(7749): afd191f8 b086b570 f602fb01 9004460c a804a901
10-28 12:39:17.829: I/DEBUG(7749): stack:
10-28 12:39:17.829: I/DEBUG(7749): 44bc8aa0 afd42664
10-28 12:39:17.829: I/DEBUG(7749): 44bc8aa4 000a7d18
10-28 12:39:17.829: I/DEBUG(7749): 44bc8aa8 00000015
10-28 12:39:17.829: I/DEBUG(7749): 44bc8aac afd182a1 /system/lib/libc.so
10-28 12:39:17.829: I/DEBUG(7749): 44bc8ab0 afd4270c
10-28 12:39:17.829: I/DEBUG(7749): 44bc8ab4 afd426b8
10-28 12:39:17.829: I/DEBUG(7749): 44bc8ab8 00000000
10-28 12:39:17.829: I/DEBUG(7749): 44bc8abc afd191d9 /system/lib/libc.so
10-28 12:39:17.829: I/DEBUG(7749): 44bc8ac0 00000001
10-28 12:39:17.829: I/DEBUG(7749): 44bc8ac4 44bc8af4
10-28 12:39:17.829: I/DEBUG(7749): 44bc8ac8 44bc8c10
10-28 12:39:17.829: I/DEBUG(7749): 44bc8acc 44984e64
10-28 12:39:17.829: I/DEBUG(7749): 44bc8ad0 44bc8b70
10-28 12:39:17.829: I/DEBUG(7749): 44bc8ad4 afd184fb /system/lib/libc.so
10-28 12:39:17.839: I/DEBUG(7749): 44bc8ad8 df002777
10-28 12:39:17.839: I/DEBUG(7749): 44bc8adc e3a070ad
10-28 12:39:17.839: I/DEBUG(7749): #00 44bc8ae0 44984e54
10-28 12:39:17.839: I/DEBUG(7749): 44bc8ae4 44984e3c
10-28 12:39:17.839: I/DEBUG(7749): 44bc8ae8 800a5368
10-28 12:39:17.839: I/DEBUG(7749): 44bc8aec afd18821 /system/lib/libc.so
10-28 12:39:17.839: I/DEBUG(7749): 44bc8af0 afd426b8
10-28 12:39:17.839: I/DEBUG(7749): 44bc8af4 fffffbdf
10-28 12:39:17.839: I/DEBUG(7749): 44bc8af8 afd1c92d /system/lib/libc.so
10-28 12:39:17.839: I/DEBUG(7749): 44bc8afc afd3ade9 /system/lib/libc.so
10-28 12:39:17.839: I/DEBUG(7749): 44bc8b00 80540c00 /data/data/com.soybea.rocket/lib/libandenginephysicsbox2dextension.so
10-28 12:39:17.839: I/DEBUG(7749): 44bc8b04 afd1c931 /system/lib/libc.so
10-28 12:39:17.839: I/DEBUG(7749): #01 44bc8b08 0000006c
10-28 12:39:17.839: I/DEBUG(7749): 44bc8b0c 80540f08 /data/data/com.soybea.rocket/lib/libandenginephysicsbox2dextension.so
10-28 12:39:17.839: I/DEBUG(7749): 44bc8b10 80540f08 /data/data/com.soybea.rocket/lib/libandenginephysicsbox2dextension.so
10-28 12:39:17.839: I/DEBUG(7749): 44bc8b14 44bc8b90
10-28 12:39:17.839: I/DEBUG(7749): 44bc8b18 00000000
10-28 12:39:17.839: I/DEBUG(7749): 44bc8b1c 80526508 /data/data/com.soybea.rocket/lib/libandenginephysicsbox2dextension.so
10-28 12:39:18.839: I/DEBUG(7749): debuggerd committing suicide to free the zombie!
10-28 12:39:18.839: I/BootReceiver(96): Copying /data/tombstones/tombstone_03 to DropBox (SYSTEM_TOMBSTONE)
10-28 12:39:18.879: I/DEBUG(17474): debuggerd: Sep 20 2011 11:21:24

首先,你得承认经常看到这样的log是要崩溃的。。。。
没有任何debug信息,你不知道是哪句出错了,你只知道,深层的so调用出问题了。。。
而你基本不可能再去修改这些文件去适应你的程序,因为
1. 能力不足
2. 即使实力超群,投入产出比也相当的不经济,有这些精力解决自己的程序才是正道~
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad,在使用box2d extension的时候你有可能会经常遇到这样的问题,尤其是当你的应用比较大,比较复杂的时候~
在下才疏学浅,只好用最土的办法,隔行打log。。。。
经过无数次的研究尝试,总结出如下规律~

它通常发生在
1. 创建Body
2. 移动Body
3. 删除Body
4. ContactListener
5. 手动设置Body对象为null
6. 还没遇到。。。。

深层次原因
同样经过无数次的试验和失败,几次挑灯夜战,越过重重GFW,翻阅无数资料,发现这类问题,基本都是深层代码的NullPointerReference所导致的

Bug解释
Box2D里有一个arraylist来维护当前所有的body,是在某个线程(可能是当前工作线程)运行的for循环,如果你在某个线程对body做了一些操作(如destory body)就会导致问题出现。。。

如何避免
1. 不要频繁大规模的创建/删除body对象,尽可能复用可以复用的对象,暂时不用的应当设置为不可见,使body sleep
2. 管理好你的线程,永远使用一个相同的线程来创建/管理/修改body对象
3. ContactListener中不要放实际方法,尽量异步调用
4. 设计模式很重要。。。

解决实例
下面是我的解决实例,仅供参考


protected static Queue<Object> deleteQueue=new LinkedList<Object>();
IUpdateHandler deleteUpdateHandler=new IUpdateHandler() {
@Override
public void onUpdate(float pSecondsElapsed) {
if (!deleteQueue.isEmpty()) {
//Do the delete body work
}
}
}
Scene.registerUpdateHandler(deleteUpdateHandler);


同样,你也可以创建多个队列,分别管理你的创建/删除/碰撞检测等操作~

最后,永远不要指望什么灵丹妙药,这些解决方法也不是狗皮膏药,贴了就好,小心的设计你的模式,认真调试代码,否则这个问题会像牛皮癣一样难以彻底根除

祝广大开发者都能更好的完成自己的项目~
<think>好的,我现在需要帮助用户解决Android中出现signal 11 (SIGSEGV)错误的问题。首先,我得理解什么是SIGSEGVSIGSEGV是段错误信号,通常是由于程序访问了未分配的内存或越界访问导致的。用户提供的引用中有一些日志和代码示例,我需要结合这些信息来分析可能的原因和解决方案。 首先看用户提供的引用[1],里面提到了操作系统的日志中有tnslsnr进程的段错误,地址在0000000000000018,这看起来像是一个空指针引用,因为地址0x18可能是一个结构体中的偏移量,而基地址为空。这种情况下,可能是在访问某个未初始化的指针或者对象已经被释放后的内存。 接下来是引用[2],里面展示了一段JNI代码,其中使用了COFFEE_TRY_JNI宏来捕获危险操作。这说明在JNI层代码中如果没有正确处理异常,可能会导致崩溃。特别是JNI函数直接调用本地方法时,如果没有适当的错误处理机制,如信号处理,可能会导致SIGSEGV未被捕获,从而引发崩溃。 引用[3]中的线程堆栈信息显示了一个Java线程被阻塞,可能与编译器线程有关,但不确定是否直接关联到用户的问题。可能需要更多的上下文,但暂时可以忽略。 现在,我需要整理常见导致SIGSEGV的原因。根据经验,主要原因包括空指针解引用、内存越界访问、使用已释放的内存、多线程竞争条件以及JNI层的错误。用户的问题集中在Android环境,所以需要特别关注JNI和本地代码的问题。 针对解决方案,首先建议使用Android Studio的调试工具,比如Address Sanitizer和NDK的调试功能,来检测内存问题。另外,检查JNI代码是否正确处理了异常,比如是否遗漏了异常检查,或者在本地代码中没有正确处理Java异常。用户提供的引用[2]中的COFFEE_TRY_JNI宏可能就是用来捕获这些错误的,所以需要确保类似的机制被正确使用。 另外,查看崩溃日志中的堆栈跟踪,确定崩溃发生的具体位置,比如是Java层还是本地代码。如果是本地代码,需要检查指针操作和内存管理。如果是Java层,可能是由于JNI调用不当导致的。 可能还需要检查是否有数组越界、缓冲区溢出等问题,尤其是在处理本地数据结构时。多线程问题也需要考虑,比如是否有竞态条件导致的内存访问冲突。 总结步骤应该是:分析日志定位问题,使用工具检测内存错误,检查JNI代码的正确性,处理异常和信号,以及代码审查和测试。同时,用户提供的引用中的示例代码和日志可以帮助具体说明这些情况,比如引用[1]中的空指针和引用[2]中的保护机制。 最后,生成的相关问题需要围绕SIGSEGV的原因、调试工具、JNI错误处理、预防措施等展开,帮助用户进一步理解和解决类似问题。</think>### AndroidSignal 11 (SIGSEGV)错误的原因及解决方案 #### 1. **错误定义** Signal 11 (`SIGSEGV`)表示段错误(Segmentation Fault),由进程尝试访问未分配的内存或越权访问内存引发。在Android开发中常见于本地代码(如JNI)或内存管理错误。 --- #### 2. **主要原因** ##### (1) **空指针解引用** - **场景**: 访问未初始化的对象指针或已释放的内存。 - **示例**: 引用[1]中的`segfault at 0000000000000018`表明尝试访问偏移量`0x18`处的内存,但基地址为空(`0x0`)。 ##### (2) **内存越界访问** - **场景**: 数组越界、缓冲区溢出(如`memcpy`操作超出分配空间)。 ##### (3) **多线程竞争** - **场景**: 多线程同时读写同一内存区域未同步(如全局变量)。 ##### (4) **JNI层错误** - **场景**: - JNI函数未正确处理Java对象引用(如未正确调用`NewGlobalRef`/`DeleteGlobalRef`)。 - 本地代码未捕获异常(如未检查`ExceptionOccurred`),导致崩溃传递到Java层[^2]。 ##### (5) **编译器/硬件问题** - **场景**: 极少数情况下由编译器优化错误或ARM指令集兼容性问题导致[^3]。 --- #### 3. **调试与解决步骤** ##### **步骤1:定位崩溃点** - **查看日志**:从`logcat`中过滤`SIGSEGV`日志,获取崩溃时的堆栈轨迹(如`backtrace`)。 - **符号化堆栈**:使用`ndk-stack`工具将原生代码地址转换为可读的函数名。 ##### **步骤2:使用内存检测工具** - **Address Sanitizer (ASan)**: ```gradle android { defaultConfig { externalNativeBuild { cmake { arguments "-DANDROID_ARM_MODE=arm", "-DANDROID_STL=c++_shared" cFlags "-fsanitize=address -fno-omit-frame-pointer" cppFlags "-fsanitize=address -fno-omit-frame-pointer" } } } } ``` - **Valgrind/Dr.Memory**:检测未初始化的内存访问(需在模拟器中运行)。 ##### **步骤3:检查JNI代码** - **引用管理**:确保本地代码中正确管理Java对象引用: ```cpp // 错误示例:未创建全局引用导致对象被GC回收 jobject localRef = env->NewObject(...); // 正确做法 jobject globalRef = env->NewGlobalRef(localRef); env->DeleteLocalRef(localRef); ``` - **异常处理**:调用JNI函数后检查异常: ```cpp jmethodID method = env->GetMethodID(cls, "method", "()V"); if (env->ExceptionCheck()) { env->ExceptionClear(); return; } ``` ##### **步骤4:信号处理** - 注册信号处理器捕获`SIGSEGV`并生成诊断信息: ```cpp #include <signal.h> void signal_handler(int sig, siginfo_t *info, void *context) { // 输出崩溃地址和线程信息 __android_log_print(ANDROID_LOG_ERROR, "Crash", "Signal %d at address %p", sig, info->si_addr); // 调用原始信号处理器(可选) exit(1); } void register_signal_handler() { struct sigaction sa; sa.sa_sigaction = signal_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO; sigaction(SIGSEGV, &sa, NULL); } ``` ##### **步骤5:代码审查与测试** - **静态分析**:使用Clang静态分析器或`cppcheck`扫描潜在问题。 - **压力测试**:通过Monkey测试或自定义高频操作复现竞争条件。 --- #### 4. **示例代码修复** 引用[2]中的`COFFEE_TRY_JNI`宏通过保护机制调用危险函数,避免崩溃直接传递到Java层: ```cpp // 修改后的JNI入口函数 jint Java_com_example_android_MyNative_foo(JNIEnv* env, jobject object) { jint retcode = 0; // 使用保护层封装本地调用 foo_protected(env, object, &retcode); return retcode; } ``` --- #### 5. **预防措施** - **启用安全模式**:在`AndroidManifest.xml`中设置`android:debuggable="true"`以捕获更多运行时信息。 - **代码规范**:使用智能指针(如`std::unique_ptr`)减少手动内存管理错误。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值