程序异常退出调试(二)

之前的那个程序异常退出的问题一直还是不好查找,奇怪的地方是在core文件中看到的堆栈信息始终都是错误的信息,参数地址指向的都是不正确的地方。然而排查了很长时间之后,也未发现有溢出的地方出现。

搁置一段时间之后,突然就想到一个问题,我们的这个服务程序是使用intel的icc编译器编译的,那么,会不会是因为icc编译的二进制文件与gcc编译器编译出来的不一样,导致在gdb调试core文件的时候不能正确识别堆栈地址?有了想法便开始验证,修改了Makefile文件之后重新编译程序,运行,压测,异常退出,调试,反复几次,排除了一些编译器不同的语法问题后,终于堆栈信息正常了,函数参数地址正确,参数值也都看得到了。

程序退出的地方定位到

FD_SET(pSocket, &writefds);

这一行。查找资料得知,FD_SET是配合select函数进行socket监听使用的,由于内核限制,其监听的文件描述符(也就是socket)的值,不能大于__FD_SETSIZE宏定义的大小,在我们的系统中,这个值是1024.这就很明白了,我们的程序因为要建立大量的连接,socket大小超过1024是有可能的,在高并发的压力测试情况下。这也是为什么之前未发现问题的原因,以前的20路压测不会触发这个问题。于是将事件监听从select改为epoll模型后重新测试,果然稳定了,不再出现异常退出的问题。

想起知乎上一个对icc和gcc编译器比较的回答中的一句话,icc虽然根据处理器特性对编译器优化做得很好,但是,整个开源代码体系的工具链都是用gcc,所以在排查问题的时候,icc编译的二进制文件可能有些奇怪的地方,毕竟,gcc,g++,gdb啥的,他们才是一家的。

posted @ 2017-03-20 09:16  重复啦  阅读(710)  评论(0编辑  收藏  举报