今天下午,我在CentOS7中重新编译了服务器,然后当我启动CentOS7时,我看到进程已被挂起。lua5.1 Static库在CentOS6中编译。CentOS6的gcc版本是4.4.7,CentOS7的gcc版本是4.8.5。然后使用gdb和gdb show进行调试:
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
下面是可能有问题的代码,InitDBFromConf将在lua中被调用,就像InitDBFromConf(lua_act_config)一样:
int SGPlatformActMgr::InitDBFromConf(lua_State* L)
{
//...
//do something
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);
//do something
//....
}
在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之前,我使用gdb break命令设置断点并打印L参数的值。我发现它是一个有效的lua_State指针。指针
- 我使用gdb step命令逐步执行InitActDB函数中的代码,发现在函数的第一行出现了分段错误。
- 我可以正常调用InitActDB函数并传入有效的L和astActInfo参数。
- 我可以在InitActDB函数中正常使用L和astActInfo参数,而不会出现分段错误或其他异常。
- 我可以找到并解决分段故障的原因和解决方案。谢谢!
1条答案
按热度按时间wvmv3b1j1#
对不起,我发现是因为SGArray<TPlatformActInfo,150> astActInfo;使用了太多堆栈空间,导致堆栈溢出。经过我的计算,一个TPlatformActInfo的大小约为40 kb,150个约为6 MB,导致堆栈溢出。但我很困惑为什么它在CentOS上工作得很好。