从Lua调用C函数触发Segmentation Fault段错误问题排查求助
从Lua调用C函数触发Segmentation Fault段错误问题排查求助
大家好,我遇到了一个从Lua调用C函数时触发Segmentation Fault的问题,折腾了好一阵没找到根源,想请大家帮忙分析下:
问题背景
今天下午我在CentOS7上重新编译了服务器程序,启动后发现进程直接挂掉了。这里有个关键前提:Lua5.1的静态库是在CentOS6上编译的,CentOS6用的gcc版本是4.4.7,而CentOS7的gcc版本是4.8.5。
GDB调试信息
我用gdb做了详细调试,得到以下关键信息:
Breakpoint 4, SGPlatformActMgr::InitDBFromConf (L=0x7fffe577901c) at gamelogic/bg/SGPlatformActMgr.cpp:454 454 ERROR_LOG("astActInfo count:%d InitActDB begin\n" , astActInfo.GetCount()); (gdb) l 449 astActInfo.Add(stActInfo); 450 451 lua_pop(L, 1); 452 } 453 454 ERROR_LOG("astActInfo count:%d InitActDB begin\n" , astActInfo.GetCount()); 455 iRet = InitActDB(L, astActInfo); 456 if (iRet) 457 { 458 ERROR_LOG("InitActDB failed:%d\n", iRet); (gdb) n 455 iRet = InitActDB(L, astActInfo); (gdb) p L $2 = (lua_State *) 0x7fffe577901c (gdb) s Program received signal SIGSEGV, Segmentation fault. 0x000000000056b0fa in InitActDB (L=<error reading variable: Cannot access memory at address 0x7fffff5e4a48>, astActInfo=<error reading variable: Cannot access memory at address 0x7fffff5e4a40>) at gamelogic/bg/SGPlatformActMgr.cpp:292 292 { (gdb) print L Cannot access memory at address 0x7fffff5e4a48
相关代码片段
问题出在从Lua调用InitDBFromConf(lua_act_config)这个C函数的流程中,相关核心代码如下:
SGPlatformActMgr::InitDBFromConf函数
int SGPlatformActMgr::InitDBFromConf(lua_State* L) { //... // 其他业务逻辑 SGArray<TPlatformActInfo, 150> astActInfo; int iTableIdx = 1; int iRet = 0; lua_pushnil(L); while (lua_next(L, iTableIdx) != 0) { TPlatformActInfo stActInfo; iRet = TransformActInfo(L, stActInfo); if (iRet) { ERROR_LOG("invalid TransformActInfo failed(%d)\n", iRet); return 0; } astActInfo.Add(stActInfo); lua_pop(L, 1); } iRet = InitActDB(L, astActInfo); // 后续业务逻辑 //.... }
TransformActInfo函数及相关宏
#define ASSIGN_LUA_VALUE(L,VAR,KEY,RET_CODE)\ do \ { \ lua_pushstring((L), (KEY)); \ lua_rawget((L), -2); \ if (!lua_isnumber((L), -1)) \ { \ ERROR_LOG("expect number but got:%s\n", lua_typename((L), lua_type(L, -1))); \ return RET_CODE; \ } \ (VAR) = lua_tonumber(L, -1); \ lua_pop((L), 1); \ } while (0) #define ASSIGN_LUA_STR_VALUE(L,VAR,KEY,RET_CODE)\ do \ { \ lua_pushstring((L), (KEY)); \ lua_rawget((L), -2); \ if (!lua_isstring((L), -1)) \ { \ ERROR_LOG("expect string but got:%s\n", lua_typename((L), lua_type(L, -1))); \ return RET_CODE; \ } \ const char* pTempStr = lua_tostring(L, -1); \ SAFE_COPYSTR_TO_CARRAY((VAR), pTempStr); \ lua_pop((L), 1); \ } while (0) int TransformActInfo(lua_State* L, TPlatformActInfo& stActInfo) { if (!lua_istable(L, -1)) { ERROR_LOG("expect a table but got:%s\n", lua_typename(L, lua_type(L, -1))); return -1; } ASSIGN_LUA_VALUE(L, stActInfo.m_uiActID, "id", -100); //..... 其他字段赋值逻辑 ASSIGN_LUA_STR_VALUE(L, stActInfo.m_acExtStr, "ext_str", -112); return 0; }
已尝试的排查步骤
- 用gdb的
watch命令监控L参数的值,确认从SGPlatformActMgr::InitDBFromConf到调用InitActDB之间,没有任何代码或操作修改或释放L指针 - 在调用
InitActDB前设置断点打印L,确认它是一个有效的lua_State指针 - 用
step命令单步进入InitActDB,发现刚进入函数第一行就触发了段错误 - 单独调用
InitActDB并传入有效的L和astActInfo参数时,函数能正常执行,没有段错误或其他异常
现在我实在搞不清为什么在完整调用链里就会出问题,想请教大家有没有遇到类似的情况,或者能帮我分析下可能的原因和解决办法?
备注:内容来源于stack exchange,提问作者sword windy
相关产品推荐
相关产品推荐

