我用select做多路复用踩到的坑------core dump

         转载地址: http://blog.csdn.net/haust_wang/article/details/50995644


既然说是用select踩到的坑,那么就先直接贴一段使用select的代码上来瞅一下:

[cpp]  view plain  copy
  1.   bool SocketAction(int fd, const char* buf, size_t len, uint64_t milli_expire) {  
  2.       struct timeval tv;  
  3.       tv.tv_sec = milli_expire / 1000;  
  4.       tv.tv_usec = (milli_expire % 1000) * 1000;  
  5.       fd_set rd_set, wt_set;  
  6.       FD_ZERO(&rd_set);  
  7.       FD_ZERO(&wt_set);  
  8.       FD_SET(fd, &rd_set);  
  9.       FD_SET(fd, &wt_set);  
  10.   
  11.       int ret = 0;  
  12.       while (true) {  
  13.           ret = select(fd+1, &rd_set, &wt_set, nullptr, &tv);  
  14.           if (ret < 0 && errno == EINTR) continue;  
  15.           break;  
  16.       }  
  17.   
  18.       if(FD_ISSET(fd, &rd_set)) {  
  19.     char rd_buf[1024] = {0};  
  20.     ret = read(fd, rd_buf, sizeof(rd_buf));  
  21.     if(ret < 0)  return false;  
  22.     printf("%s\n", rd_buf);  
  23. else if(FD_ISSET(fd, &wt_set)) {  
  24.     ret = send(fd, buf, len, 0);  
  25.     if(ret < 0) return false;  
  26. }  
  27.   
  28.       return true;  
  29.   }  

上面的代码着实很简单,只是针对某一个socket fd进行读写操作,从逻辑上来说应该是没有任何问题的。然而这个在实际的使用过程中确实会出现问题,我们程序中封装了socket的操作,如上代码的方式使用了select。在出现大量的socket连接时,会出现宕机现象,并且宕机生成的core文件的堆栈也莫名其妙的被破坏了。遇到这个情况时,我直接被震惊了,因为仔细检查了代码确实没有发现任何问题,为什么每次都是连接数达到快1500的时候就出现宕机呢?

刚开始以为是其他的逻辑出了问题,于是仔细检查了其他的逻辑确实也没有发现存在任何问题,并且从堆栈被破坏的情况上分析,也怀疑是某个使用中出现了数组越界访问引发的。但在整个逻辑中使用的都是stl里的容器,没有申请数组,出现读写越界着实无法理解。

此后只能怀疑底层封装的问题,在一步步尝试注释代码的过程中,发现select使用的地方出现了问题。那么问题究竟在哪里呢?

 int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);


 nfds is the highest-numbered file descriptor in any of the three sets, plus 1.

在select的使用manual中,select的定义和nfds的说明如上所示,也只是说明了select的nfds是最大的文件描述符+1,在实际的使用过程中也确实有这么使用,好像也确实没有问题。然而,不止这么简单,select的文件描述符的最大值实际是有一个潜在规则的,那就是select的最大文件描述符最大是1024,该值在centor os系统中,定义在文件/usr/include/sys/select.h文件中,如下:

   78 /* Maximum number of file descriptors in `fd_set'.  */
   79 #define FD_SETSIZE      __FD_SETSIZE

而__FD_SETSIZE则定义在:/usr/include/bits/typesizes.h 中,如下:

   62 /* Number of descriptors that can fit in an `fd_set'.  */
   63 #define __FD_SETSIZE        1024      

这下可以理解了吧,在socket大于1024时,文件描述符自然就大于1024,则在使用select时访问的大小就实际超越了系统中对于select的支持,因此出现读写越界,造成程序的宕机。

这次所踩的坑非常隐晦,但也说明了一个问题,在使用系统接口时需要慎重。虽然可能使用方法并没有错误,但也要在使用的时候多注意其“潜规则”。


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值