网络编程中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 int类型,left=-16时left>0为true!!!所以之后会发生死循环.

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

                                        ......

解决:

修改的话有两种方式:

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

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

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

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

猜你喜欢

转载自blog.csdn.net/u012906122/article/details/108037828
今日推荐