gdb调试程序出错,正常运行却没有错误

glsssd 2012-11-20 04:06:07
两进程A和B通过网络连接,A先给B发送一个数据包,B收到后给A发回相应信息。现在B先启动,再启动A,接着马上把A杀掉,测试网络中断时程序的处理情况。如果用gdb调试B进程,发现B在给A发送数据时出现错误;但是如果不用gdb调试,直接运行B进程,就没有错误,网络中断导致发生数据错误,底层抛出异常,上层有正确捕捉到。不知道这是什么原因?用gdb调试时出错时的堆栈信息为:

(gdb) bt
#0 0xb7fa2410 in __kernel_vsyscall ()
#1 0xb7abf711 in send () from /lib/tls/i686/cmov/libc.so.6
#2 0x0805fb83 in SockBufferO<ListBuffer, RC4Filter>::write (this=0x8621588,
so=@0x8621148, msg=0x8b6d9e0 "\024\022\001", size=70164)
at SockBufferO.h:39
#3 0x0805eb49 in TcpSocket::SendBin (this=0x8621148, ip=421729196,
port=46339, pPkg=@0xbf83e260, uri=31003394) at TcpSocket.cpp:229
#4 0x0804dfca in DaemonManager::tcpSend (this=0x8075660, pSocket=0x8621148,
msg=@0xbf83e260, uri=31003394) at DaemonManager.cpp:275
#5 0x080500f5 in DaemonManager::handleNewRegs (this=0x8075660)
at DaemonManager.cpp:520
#6 0x0804bdbb in SelectorEPoll::TimerCheck (this=0x8075760, tNow=1353396986)
at TimerHandler.h:21
#7 0x0804c34a in SelectorEPoll::Run (this=0x8075760) at selector_epoll.cpp:121
#8 0x0804b3d8 in main (sz=2717, args=0x8b6d9e0) at main.cpp:115

求高人指点,感激不尽!
...全文
777 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
glsssd 2012-11-21
  • 打赏
  • 举报
回复
非常感谢 fdl19881 耐心的回答,现在这个问题已经找到: send失败后默认是会发出SIGPIPE的信号,虽然在程序中有忽略这个信号,但是gdb默认是没有忽略这个信号的,所以gdb先于进程发现这个信息就会终止进程。如果要在gdb中忽略这个信号,可以先设置: handle SIGPIPE nostop 我这样设置后,再次在gdb中调试程序,现在有捕捉到底层抛出的异常,进程也没有被终止掉。
glsssd 2012-11-21
  • 打赏
  • 举报
回复
引用 5 楼 fdl19881 的回复:
引用 3 楼 glsssd 的回复:引用 1 楼 fdl19881 的回复:初步猜测是你使用了未初始化的变量, 是否出现segment default? 收到什么信号了? 调试时会提示是什么错误呀? 你最后是调用了send,send好像未返回就出现什么错误了,一般只可能是segment default.即非法访问内存! 首先非常感谢你的回答! gdb调试出错时……
程序的开始有忽略SIGPIPE,即有加signal(SIGPIPE, SIG_IGN);同时在send返回-1时也有判断,我在程序中发现send返回-1后就抛出异常,然后在上层捕捉这个异常,不用gdb调试的时候有捕捉到这个异常;但用gdb调试的时候一直到出错都没有捕捉到这个异常,进程最后挂掉
fdl19881 2012-11-21
  • 打赏
  • 举报
回复
引用 3 楼 glsssd 的回复:
引用 1 楼 fdl19881 的回复:初步猜测是你使用了未初始化的变量, 是否出现segment default? 收到什么信号了? 调试时会提示是什么错误呀? 你最后是调用了send,send好像未返回就出现什么错误了,一般只可能是segment default.即非法访问内存! 首先非常感谢你的回答! gdb调试出错时没有提示segment defaul……
这就更简单了呀,当对tcp对端关闭时(对端进程被你KILL后,会由操作系统自动关闭其tcp连接),你send一次就会收到RST包,然后再send一下就会收到SIGPIPE信号,此信号默认动作是结束进程!!此时send也是会返回-1的,errno == EPIPE 所以你在程序开始部分加上一句 signal(SIGPIPE, SIG_IGN);将SIGPIPE忽略即可。这样send就不会出错了,同时会返回-1,errno = EPIPE linux基础不牢。
glsssd 2012-11-21
  • 打赏
  • 举报
回复
引用 2 楼 fdl19881 的回复:
还有,用kill -9杀死进程能测试网络中断吗? 印象中进程收到SIGKILL信号后,虽然肯定会结束,但其网络连接sockfd会由操作系统调用_exit()关闭,而这个会正常关闭连接。所以也测不到网络中断的情况! 这个自行验证。 你检查下传给send函数的buf与len是否正确。 最简单的方法,把send暂时替换成buf[0] = 0x55;buf[len-1……
传给send函数的buf和len是正确的
glsssd 2012-11-21
  • 打赏
  • 举报
回复
引用 1 楼 fdl19881 的回复:
初步猜测是你使用了未初始化的变量, 是否出现segment default? 收到什么信号了? 调试时会提示是什么错误呀? 你最后是调用了send,send好像未返回就出现什么错误了,一般只可能是segment default.即非法访问内存!
首先非常感谢你的回答! gdb调试出错时没有提示segment default?出错时的提示的是: Program received signal SIGPIPE, Broken pipe. [Switching to Thread 0xb79bf6c0 (LWP 7112)] 0xb7fe3410 in __kernel_vsyscall ()
fdl19881 2012-11-20
  • 打赏
  • 举报
回复
还有,用kill -9杀死进程能测试网络中断吗? 印象中进程收到SIGKILL信号后,虽然肯定会结束,但其网络连接sockfd会由操作系统调用_exit()关闭,而这个会正常关闭连接。所以也测不到网络中断的情况! 这个自行验证。 你检查下传给send函数的buf与len是否正确。 最简单的方法,把send暂时替换成buf[0] = 0x55;buf[len-1] = 0x55;调试时,看是否执行这句时出现segment default. 正常运行时,某些字段碰巧是对的;而调试时,可能gdb会填充未初始化的字段,正好使得出错。
fdl19881 2012-11-20
  • 打赏
  • 举报
回复
初步猜测是你使用了未初始化的变量, 是否出现segment default? 收到什么信号了? 调试时会提示是什么错误呀? 你最后是调用了send,send好像未返回就出现什么错误了,一般只可能是segment default.即非法访问内存!

23,121

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧