网络编程中read使用错误引起的崩溃

网络编程中,基础接口read的使用要格外注意,先上有问题的代码:

int socketTCP::readn(char *buf, size_t len){
    int ret = 0;
    size_t left = len;

    while(left > 0){
        ret = ::read(sock_, buf, len);
        if (ret < 0) {
            return -1;
        }
        if (ret == 0) {
            break;
        }
        buf += ret;
        left -= ret;
    }

    return len-left;
}

崩溃现象:

崩溃的地址每次不一样,崩溃地址随机。

复现方法:

客户端每次给服务端发送的包字节大小是32B:

32B,32B,32B,

正常情况下,read接收的包字节大小是:

32B,32B,32B,...

异常情况下,read接收的包字节大小是:

32B,16B,32B,...

分析:

一旦read返回的ret值为16,那么上述代码即陷入“死循环”中,直到buf越界,出现Segmentation Fault.

之所以每次崩溃地址随机,是因为buf每次越界的地址随机。

为什么会"死循环呢"?举例分析下:

(1) readn->32B    left=32,ret=32,left=32-32=0 退出循环 

(2) readn->32B    left=32,ret=16,left=32-16=16 

                                        ret=32,left=16-32=-16     //read还是会读len个字节,ret=32

因为left是size_t类型,而size_t是unsigned类型,left=-16时left>0为true!!!所以之后会发生死循环.

                                        ret=32,left=-16-32=-48

                                        ......

size_t的真实类型与操作系统有关。
在32位架构中被普遍定义为:

typedef   unsigned int size_t;

而在64位架构中被普遍定义为:

typedef  unsigned long size_t;

解决:

修改的话有两种方式:

(1)size_t left=len;改为int left=len;

目的是要当left<0时退出循环。

(2)read(sock_,buf,len);改为read(sock_,buf,left);

目的是保证left会==0,退出循环。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值