UDP套接字超时循环的内存错误

时间:2013-09-19 14:07:54

标签: c sockets udp unix-socket

我正在编写一个UDP发送/接收功能,当它在一定时间内没有得到回复时会超时,并重新发送数据包。我正在使用socksetopt设置超时,这一切似乎都有效,直到我进入最后一次迭代,然后出现大量错误消息。

我的代码在这里:

int itermax=10;
int itercount=0;

int send_and_receive(void* message, void* reply, int do_send, int expect_reply){
    struct sockaddr_in serv_addr;
    int sockfd, i, slen=sizeof(serv_addr);
    int buflen = BUFLEN;
    void* buf = NULL;
    struct timeval tv;
    int n_timeouts=1;
    int retval;

    printf("N = %d\n", itercount);
    itercount++;

    if ( (strlen(message)) >= BUFLEN)
        err("Message too big");

    buf = malloc(buflen);

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
        err("socket");

    tv.tv_sec = 1;
    tv.tv_usec = 0;
    if( setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) < 0 ){
        err("Setting Timout"); 
    }

    bzero(&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    if (inet_aton(IP_ADDRESS, &serv_addr.sin_addr)==0)
        err("inet_aton() failed\n");

    if(do_send == TRUE){
        strcpy(buf, message);
        if (sendto(sockfd, buf, buflen, 0, (struct sockaddr*)&serv_addr, slen)==-1)
            err("sendto()");
    }

    if (expect_reply == TRUE){
        if( recvfrom(sockfd, buf, buflen, 0, (struct sockaddr*)&serv_addr, &slen) == -1){

            close(sockfd);
            free(buf);
            if(itercount < itermax){
                send_and_receive(message, reply, do_send, expect_reply);
            }
            else{
                perror("recvfrom");
                return -1;
            }
        }
    }

    memcpy(reply, buf, BUFLEN);
    close(sockfd);
    free(buf);
    return 0;
}

错误信息:


recvfrom: Resource temporarily unavailable
*** glibc detected *** : double free or corruption (top): 0x083af008 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(+0x6e341)[0xa8a341]
/lib/tls/i686/cmov/libc.so.6(+0x6fb98)[0xa8bb98]
/lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0xa8ec7d]
[0x8048a44]
[0x80489ff]
[0x80489ff]
[0x80489ff]
[0x80489ff]
[0x80489ff]
[0x80489ff]
[0x80489ff]
[0x80489ff]
[0x8048a84]
[0x8048c35]
[0xac000000]
======= Memory map: ========
00173000-00174000 r-xp 00000000 00:00 0          [vdso]
008a6000-008c3000 r-xp 00000000 08:01 2224682    /lib/libgcc_s.so.1
008c3000-008c4000 r--p 0001c000 08:01 2224682    /lib/libgcc_s.so.1
008c4000-008c5000 rw-p 0001d000 08:01 2224682    /lib/libgcc_s.so.1
00a1c000-00b75000 r-xp 00000000 08:01 2362849    /lib/tls/i686/cmov/libc-2.11.1.so
00b75000-00b77000 r--p 00159000 08:01 2362849    /lib/tls/i686/cmov/libc-2.11.1.so
00b77000-00b78000 rw-p 0015b000 08:01 2362849    /lib/tls/i686/cmov/libc-2.11.1.so
00b78000-00b7b000 rw-p 00000000 00:00 0 
00b84000-00b9f000 r-xp 00000000 08:01 2230784    /lib/ld-2.11.1.so
00b9f000-00ba0000 r--p 0001a000 08:01 2230784    /lib/ld-2.11.1.so
00ba0000-00ba1000 rw-p 0001b000 08:01 2230784    /lib/ld-2.11.1.so
08048000-08049000 r-xp 00000000 08:01 667121     /home/james/BitBucket/rtig/Code/c
08049000-0804a000 r--p 00000000 08:01 667121     /home/james/BitBucket/rtig/Code/c
0804a000-0804b000 rw-p 00001000 08:01 667121     /home/james/BitBucket/rtig/Code/c
083af000-083d0000 rw-p 00000000 00:00 0          [heap]
b7600000-b7621000 rw-p 00000000 00:00 0 
b7621000-b7700000 ---p 00000000 00:00 0 
b7732000-b7733000 rw-p 00000000 00:00 0 
b7745000-b7748000 rw-p 00000000 00:00 0 
bfc70000-bfc85000 rw-p 00000000 00:00 0          [stack]
Aborted

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

正在发生双重免费,因为您在此处释放缓冲区:

if( recvfrom(sockfd, buf, buflen, 0, (struct sockaddr*)&serv_addr, &slen) == -1){
    close(sockfd);
    free(buf);

然后当您退出该功能时再次:

memcpy(reply, buf, BUFLEN);
close(sockfd);
free(buf);
return 0;

要解决此问题,请在释放buf后,将指针设置为NULL

if( recvfrom(sockfd, buf, buflen, 0, (struct sockaddr*)&serv_addr, &slen) == -1){
    close(sockfd);
    free(buf);
    buf = NULL;

还有一个问题是,您可能在免费后可以从buf阅读。 (请注意上面的memcpy。)