signal 11 (SIGSEGV)错误排查

jni调试最蛋疼的就是signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4这种错误,爆出来完全不知道是哪句代码造成的,很难定位到问题所在,网上很多人说是内存原因,还有说是空指针,不一而论。
我的错误是这样的:

02-16 14:54:53.041 20897-20897/? I/AEE/AED: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4
02-16 14:54:53.058 20897-20897/? I/AEE/AED:     r0 00000001  r1 00000002  r2 00000000  r3 0000002f
02-16 14:54:53.058 20897-20897/? I/AEE/AED:     r4 00000000  r5 f4489000  r6 f4400000  r7 f6fb3c0c
02-16 14:54:53.058 20897-20897/? I/AEE/AED:     r8 f48000c0  r9 f6fb3c0c  sl 00000001  fp 00000002
02-16 14:54:53.058 20897-20897/? I/AEE/AED:     ip f6fb3c24  sp dc144060  lr 00000000  pc f6f7f566  cpsr 600f0030
02-16 14:54:53.059 20897-20897/? I/AEE/AED: backtrace:
02-16 14:54:53.059 20897-20897/? I/AEE/AED:     #00 pc 00042566  /system/lib/libc.so (je_arena_dalloc_bin_locked+365)
02-16 14:54:53.059 20897-20897/? I/AEE/AED:     #01 pc 0004fa0b  /system/lib/libc.so (je_tcache_bin_flush_small+234)
02-16 14:54:53.059 20897-20897/? I/AEE/AED:     #02 pc 0004a33f  /system/lib/libc.so (ifree+446)
02-16 14:54:53.059 20897-20897/? I/AEE/AED:     #03 pc 00035775  /data/app/我的包名-1/lib/arm/libjni-lib.so (std::__ndk1::basic_string, std::__ndk1::allocator >::~basic_string()+148)
02-16 14:54:53.059 20897-20897/? I/AEE/AED:     #04 pc 00086087  /data/app/我的包名-1/lib/arm/libjni-lib.so (WPZHandler::OnRspQryPosition(TradingLibFast::RspQryPositionResponse*)+2518)
02-16 14:54:53.059 20897-20897/? I/AEE/AED:     #05 pc 0004451d  /data/app/我的包名-1/lib/arm/libjni-lib.so (TradingLibFast::TLClient::HandleMessage(TradingLibFast::Message&)+964)
02-16 14:54:53.059 20897-20897/? I/AEE/AED:     #06 pc 00041083  /data/app/我的包名-1/lib/arm/libjni-lib.so (TradingLibFast::TLClient::RecvFun()+226)
02-16 14:54:53.059 20897-20897/? I/AEE/AED:     #07 pc 00066cfb  /data/app/我的包名-1/lib/arm/libjni-lib.so (fastdelegate::FastDelegate0::operator()() const+94)
02-16 14:54:53.059 20897-20897/? I/AEE/AED:     #08 pc 00066889  /data/app/我的包名-1/lib/arm/libjni-lib.so (TradingLibFast::TLThread::ProcessInThread()+68)
02-16 14:54:53.059 20897-20897/? I/AEE/AED:     #09 pc 00066837  /data/app/我的包名-1/lib/arm/libjni-lib.so (TradingLibFast::ThreadFunc(void*)+26)
02-16 14:54:53.059 20897-20897/? I/AEE/AED:     #10 pc 00017003  /system/lib/libc.so (__pthread_start(void*)+30)
02-16 14:54:53.059 20897-20897/? I/AEE/AED:     #11 pc 0001506f  /system/lib/libc.so (__start_thread+6)

然后就是nativeCrashListener,这个log其实已经很清晰了,记得一定不要过滤,选择no Filters,日志级别选择Verbose最低级别,这样才能看到最全的log信息。je_arena_dalloc_bin_locked显示就是内存处理出问题了,jni代码出问题导致了系统错误。再往下包含“我的包名”的log信息就显示了错误的具体位置,越上面就是越具体的位置,越下面范围就越广,这里大致就定位了问题代码大概在哪几行。不过这几行我纠结了许久,因为觉得没有问题,闪退只是偶现,后来看到另外一篇文章:常见 core dump 原因分析signal 11 - SIGSEGV,说signal 11 (SIGSEGV)是由于内存释放不当(多次释放或者空释放)或者空指针引起的,遂检查,终于发现了问题:
在调用NewStringUTF方法的时候使用了ReleaseStringUTFChars进行释放,这个释放内存的方法并不能在此处使用,应该使用DeleteLocalRef来释放引用即可。
jni具体内存释放对应方法如下:
总体原则:释放所有对object的引用

1.FindClass
例如,

jclass ref= (env)->FindClass("java/lang/String"); 
env->DeleteLocalRef(ref); 

2.NewString/ NewStringUTF/NewObject/NewByteArray
例如,

jstring     (*NewString)(JNIEnv*, const jchar*, jsize);    
const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*);     void        (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*); 
jstring     (*NewStringUTF)(JNIEnv*, const char*);    
const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*);     void        (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*); 
env->DeleteLocalRef(ref); 

3.GetObjectField/GetObjectClass/GetObjectArrayElement

jclass ref = env->GetObjectClass(robj); 
env->DeleteLocalRef(ref);  

4.GetByteArrayElements和GetStringUTFChars

jbyte* array= (*env)->GetByteArrayElements(env,jarray,&isCopy); 
(*env)->ReleaseByteArrayElements(env,jarray,array,0); 
const char* input =(*env)->GetStringUTFChars(env,jinput, &isCopy); 
(*env)->ReleaseStringUTFChars(env,jinput,input); 

5.NewGlobalRef/DeleteGlobalRef
jobject (NewGlobalRef)(JNIEnv, jobject);
void (DeleteGlobalRef)(JNIEnv, jobject);
例如,

jobject ref= env->NewGlobalRef(customObj); 
env->DeleteGlobalRef(customObj); 

改完果然就没有再闪退了!

你可能感兴趣的:(signal 11 (SIGSEGV)错误排查)