gdb - 确定分段错误的原因

时间:2015-01-20 16:23:27

标签: c++ linux gdb server coredump

我的服务器/客户端系统在我的机器上运行良好。但它的核心转储在其中一个用户机器上(操作系统: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 ?? ()

我按照嵌套的调用。他们是对的。

1 个答案:

答案 0 :(得分:2)

memcpy的问题是源位置与目标的类型不同。

您应该使用inet_addr将地址从字符串转换为二进制

a4.sin_addr = inet_addr(pHost->h_addr);

以前的代码可能不起作用,具体取决于实现(有些我的返回struct in_addr,其他代码将返回unsigned long,但原则是相同的。