我的服务器/客户端系统在我的机器上运行良好。但它的核心转储在其中一个用户机器上(操作系统:Centos 5)。由于我无法访问用户的计算机,因此我构建了一个调试模式二进制文件并要求用户尝试它。在大约2天的跑步后,坠机确实再次发生。他发给我核心转储文件。使用gdb加载核心转储文件,它确实显示了崩溃位置,但我不明白原因(对不起,我之前的经验主要是Windows。我对Linux / gdb没有太多经验)。我想得到你的意见。谢谢!
1。用户计算机上的/ var / log / messages显示了段错误:
Jan 16 09:20:39 LPZ08945内核:LSystem [4688]:段错误0000000000000000 rip 00000000080e6433 rsp 00000000f2afd4e0错误4
此消息表示指令指针80e6433和堆栈指针f2afd4e0存在段错误。看起来程序试图在地址0处读/写。
2。将核心转储文件加载到gdb中,它显示崩溃位置:
$ gdb LSystem core.19009
GNU gdb(GDB)CentOS(7.0.1-45.el5.centos)
...(gdb的多行输出省略)
核心由`。/ LSystem'生成。
程序终止于信号11, 分段错误。
在liccomm / LClient.cpp的CLClient :: connectToServer(this = 0xf2afd898,conn = 11)中的'#0'0x080e6433:214
214 memcpy((char *)&(a4.sin_addr),pHost-> h_addr,pHost-> h_length);
gdb说崩溃发生在第214行?
第3。框架信息。 (在第0帧)
(gdb)信息框
堆栈级别0,帧位于0xf2afd7e0:
CLClient :: connectToServer中的eip = 0x80e6433(liccomm / LClient.cpp:214);保存了eip 0x80e6701
由帧调用0xf2afd820
源语言c ++。
Arglist在0xf2afd7d8,args:this = 0xf2afd898,conn = 11
当地人在0xf2afd7d8,前一帧的sp是0xf2afd7e0
保存的寄存器:
ebx位于0xf2afd7cc,ebp位于0xf2afd7d8,esi位于0xf2afd7d0,edi位于0xf2afd7d4,eip位于0xf2afd7dc
框架位于f2afd7e0,为什么它与第1部分的rsp不同,后者是f2afd4e0?我想用户可能向我提供了不匹配的核心转储文件(其pid为19009)和/ var / log / messages文件(表示pid 4688)。
4。来源
(gdb)list +
209
210 //pHost is declared as struct hostent* and 'pHost = gethostbyname(serverAddress);'
211 memset( &a4, 0, sizeof(a4) );
212 a4.sin_family = AF_INET;
213 a4.sin_port = htons( nPort );
214 memcpy((char *) & (a4.sin_addr), pHost->h_addr, pHost->h_length);
215
216 aalen = sizeof(a4);
217 aa = (struct sockaddr *)&a4;
我看不出第214行有什么问题。这部分代码必须在2天的运行时间内运行多次。
5。变量
由于gdb表明214行是罪魁祸首。我打印了一切。
memcpy((char *) & (a4.sin_addr), pHost->h_addr, pHost->h_length);
(gdb)打印a4.sin_addr
$ 1 = {s_addr = 0}
(gdb)print&(a4.sin_addr)
$ 2 =(in_addr *)0xf2afd794
(gdb)print pHost-> h_addr_list [0]
$ 3 = 0xa24af30“\ 202} \ 204 \ 250”
(gdb)打印pHost-> h_length
$ 4 = 4
(gdb)print memcpy
$ 5 = {} 0x2fcf90
所以我基本上打印了第214行的所有内容。('pHost-> h_addr_list [0]'是'pHost-> h_addr',因为'#define h_addr h_addr_list [0]')
我无法发现任何错误。你有什么可疑的东西吗?内存是否可能在其他地方被破坏?感谢您的帮助!
[已编辑] 6.返回跟踪
(gdb)bt
在liccomm / LClient.cpp的CLClient :: connectToServer(this = 0xf2afd898,conn = 11)中的'#0'0x080e6433:214
在liccomm / LClient.cpp的CLClient :: connectToLMServer(this = 0xf2afd898)中的'#1'0x080e6701:121
...(省略第2~7帧,不相关)
位于LManager.cpp的handleConnectionStarter(par = 0xf3563f98)中的'#8'0x080937f2:166
'#9'0xf7f5fb41 in ?? ()
'#10'0xf3563f98 in ?? ()
'#11'0xf2aff31c在? ()
'#12'0x00000000 in ?? ()
我按照嵌套的调用。他们是对的。
答案 0 :(得分:2)
memcpy的问题是源位置与目标的类型不同。
您应该使用inet_addr
将地址从字符串转换为二进制
a4.sin_addr = inet_addr(pHost->h_addr);
以前的代码可能不起作用,具体取决于实现(有些我的返回struct in_addr
,其他代码将返回unsigned long
,但原则是相同的。