日期:2014-05-16  浏览次数:20858 次

gdb调试程序出错,正常运行却没有错误
两进程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

求高人指点,感激不尽!
------解决方案--------------------
初步猜测是你使用了未初始化的变量,
是否出现segment default? 收到什么信号了? 调试时会提示是什么错误呀?
你最后是调用了send,send好像未返回就出现什么错误了,一般只可能是segment default.即非法访问内存!
------解决方案--------------------
还有,用kill -9杀死进程能测试网络中断吗? 
印象中进程收到SIGKILL信号后,虽然肯定会结束,但其网络连接sockfd会由操作系统调用_exit()关闭,而这个会正常关闭连接。所以也测不到网络中断的情况! 这个自行验证。

你检查下传给send函数的buf与len是否正确。
最简单的方法,把send暂时替换成buf[0] = 0x55;buf[len-1] = 0x55;调试时,看是否执行这句时出现segment default.

正常运行时,某些字段碰巧是对的;而调试时,可能gdb会填充未初始化的字段,正好使得出错。
------解决方案--------------------
引用:
引用:初步猜测是你使用了未初始化的变量,
是否出现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基础不牢。