Cocos 2dx项目lua调用OC出现卡死但不闪退的坑
Posted jxst441192
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cocos 2dx项目lua调用OC出现卡死但不闪退的坑相关的知识,希望对你有一定的参考价值。
最近新上线的一个游戏,发现线上游戏有部分功能在点击的时候出现了没有反应的情况。通过调试源码,发现是原生OC的代码出现了崩溃,但是比较奇怪的是线上的Bugly没有任何记录,这个功能属于高频高能,而且又是非常重要的功能,所以我下定决心查个明白。后来通过查看cocos2d_lua_bindings的源码,发现是cocos2d_lua_bindings中的CCLuaObjcBridge.mm166行把这个崩溃给catch了。。所以质检部门也没发现这个错误,可能是以为游戏只是卡了下,真的是坑死人不偿命啊。
下面是CCLuaObjcBridge.mm的源码
/** className methodName args */ int LuaObjcBridge::callObjcStaticMethod(lua_State *L) { if (lua_gettop(L) != 3 || !lua_isstring(L, -3) || !lua_isstring(L, -2)) { lua_pushboolean(L, 0); lua_pushinteger(L, kLuaBridgeErrorInvalidParameters); return 2; } const char *className = lua_tostring(L, -3); const char *methodName = lua_tostring(L, -2); if (!className || !methodName) { lua_pushboolean(L, 0); lua_pushinteger(L, kLuaBridgeErrorInvalidParameters); return 2; } Class targetClass = NSClassFromString([NSString stringWithCString:className encoding:NSUTF8StringEncoding]); if (!targetClass) { lua_pushboolean(L, 0); lua_pushinteger(L, kLuaBridgeErrorClassNotFound); return 2; } SEL methodSel; bool hasArguments = lua_istable(L, -1); if (hasArguments) { NSString *methodName_ = [NSString stringWithCString:methodName encoding:NSUTF8StringEncoding]; methodName_ = [NSString stringWithFormat:@"%@:", methodName_]; methodSel = NSSelectorFromString(methodName_); } else { methodSel = NSSelectorFromString([NSString stringWithCString:methodName encoding:NSUTF8StringEncoding]); } if (methodSel == (SEL)0) { lua_pushboolean(L, 0); lua_pushinteger(L, kLuaBridgeErrorMethodNotFound); return 2; } NSMethodSignature *methodSig = [targetClass methodSignatureForSelector:(SEL)methodSel]; if (methodSig == nil) { lua_pushboolean(L, 0); lua_pushinteger(L, kLuaBridgeErrorMethodSignature); return 2; } @try { NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; [invocation setTarget:targetClass]; [invocation setSelector:methodSel]; NSUInteger returnLength = [methodSig methodReturnLength]; const char *returnType = [methodSig methodReturnType]; if (hasArguments) { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; lua_pushnil(L); while (lua_next(L, -2)) { NSString *key = [NSString stringWithCString:lua_tostring(L, -2) encoding:NSUTF8StringEncoding]; switch (lua_type(L, -1)) { case LUA_TNUMBER: [dict setObject:[NSNumber numberWithFloat:lua_tonumber(L, -1)] forKey:key]; break; case LUA_TBOOLEAN: [dict setObject:[NSNumber numberWithBool:lua_toboolean(L, -1)] forKey:key]; break; case LUA_TSTRING: [dict setObject:[NSString stringWithCString:lua_tostring(L, -1) encoding:NSUTF8StringEncoding] forKey:key]; break; case LUA_TFUNCTION: int functionId = retainLuaFunction(L, -1, NULL); [dict setObject:[NSNumber numberWithInt:functionId] forKey:key]; break; } lua_pop(L, 1); } [invocation setArgument:&dict atIndex:2]; [invocation invoke]; } else { [invocation invoke]; } lua_pushboolean(L, 1); if (returnLength > 0) { if (strcmp(returnType, "@") == 0) { id ret; [invocation getReturnValue:&ret]; pushValue(L, ret); } else if (strcmp(returnType, "c") == 0) // BOOL { char ret; [invocation getReturnValue:&ret]; lua_pushboolean(L, ret); } else if (strcmp(returnType, "i") == 0) // int { int ret; [invocation getReturnValue:&ret]; lua_pushinteger(L, ret); } else if (strcmp(returnType, "f") == 0) // float { float ret; [invocation getReturnValue:&ret]; lua_pushnumber(L, ret); } else { NSLog(@"not support return type = %s", returnType); lua_pushnil(L); } } else { lua_pushnil(L); } return 2; } @catch (NSException *exception) //就是这处代码导致崩溃被catch了,正确的做法应该是测试阶段直接throw exception,上线后通过bugly手动上报这个exception对象
{ NSLog(@"EXCEPTION THROW: %@", exception); lua_pushboolean(L, 0); lua_pushinteger(L, kLuaBridgeErrorExceptionOccurred); return 2; } }
以上是关于Cocos 2dx项目lua调用OC出现卡死但不闪退的坑的主要内容,如果未能解决你的问题,请参考以下文章