我正在编写一个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
非常感谢任何帮助。
答案 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
。)