2014-10-31 80 views
1

我无法弄清我的代码的奇怪行为。 基本上,程序监听一个TCP端口,获取启动/停止命令后,它创建一个卷曲线程并开始下载流。 问题是,每次下载流时,程序都会在共享内存中增长。在许多下载之后,程序停止工作。 - 它接受启动/停止命令,但只下载一小块数据。我认为,有一些内存泄漏。 代码:从Valgrind的C线程和卷曲内存泄漏

#include <stdio.h> 
#include <errno.h> 
#include <sys/socket.h> 
#include <resolv.h> 
#include <arpa/inet.h> 
#include <errno.h> 
#include <pthread.h> 
#include <stdlib.h> 
#include <curl/curl.h> 



#define MY_PORT   8888 
#define MAXBUF   1024 
int hour=1,min=1,sec=1,year=0,month=0,mday=0; 
int stop=0; 
static void daemon(); 
CURL *curl; 
CURLcode res; 

size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) { 
    size_t written; 
     written = fwrite(ptr, size, nmemb, stream); 
     if(stop) 
      return -1; 
     return written; 
} 
    void * curl_thread(){ 

     FILE *fp; 
     char format[] = "/root/test/archive_%d-%s-%s_%s.%s.%s.mp3"; 
     char outfilename[sizeof format+100]; 
     char mi[3]; 
     char mth[3]; 
     char dom[3]; 
     char hrs[3]; 
     char secs[3]; 
     sprintf(mth, "%d", month); 
     sprintf(dom, "%d", mday); 
     sprintf(hrs, "%d", hour); 
     sprintf(mi, "%d", min); 
     sprintf(secs, "%d", sec); 
     if (month<10){ 
       sprintf(mth, "0%d", month);} 
     if (mday<10){ 
       sprintf(dom, "0%d", mday); } 
      if (hour<10){ 
       sprintf(hrs, "0%d", hour); } 
     if (min<10){ 
       sprintf(mi, "0%d", min);} 
     if (sec<10){ 
       sprintf(secs, "0%d", sec);} 
     sprintf(outfilename,format,year,mth,dom,hrs,mi,secs); 
     curl = curl_easy_init(); 
     if(curl) { 
       fp = fopen(outfilename,"wb"); 
       curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:8000/stream.mp3"); 
       curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); 
       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 
       curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); 
       curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); 
       curl_easy_setopt(curl, CURLOPT_USERAGENT, "curl capture"); 
       res = curl_easy_perform(curl); 
       curl_easy_cleanup(curl); 
       fclose(fp); 
     } 
     stop=0; 
     pthread_exit(0); 
} 




void time_date(void){ 
     time_t rawtime; 
     time (&rawtime); 
     struct tm *tm_struct = localtime(&rawtime); 
     hour = tm_struct->tm_hour; 
     min = tm_struct->tm_min; 
     sec= tm_struct->tm_sec; 
     year=tm_struct->tm_year + 1900; 
     month=tm_struct->tm_mon + 1; 
     mday=tm_struct->tm_mday; 
} 

void daemon(){ 
     pid_t mypid; 
     FILE *pid; 
     mypid=fork(); 
     if (mypid){ 
       pid=fopen("acapt.pid","w"); 
       fprintf(pid,"%i",mypid); 
       exit (0); 
     } 
} 


int main(int Count, char *Strings[]) 
{ 
    daemon(); 
    time_date(); 
    int thread=0; 

    int sockfd; 
    struct sockaddr_in self; 
    char buffer[MAXBUF]; 
    char buff[MAXBUF]; 
//---Create streaming socket---*/ 
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    { 
     perror("Socket"); 
     exit(errno); 
    } 
///Initialize address/port structure---*/ 
    bzero(&self, sizeof(self)); 
    self.sin_family = AF_INET; 
    self.sin_port = htons(MY_PORT); 
    self.sin_addr.s_addr = INADDR_ANY;//*---Assign a port number to the socket---*/ 
    if (bind(sockfd, (struct sockaddr*)&self, sizeof(self)) != 0) 
    { 
     perror("socket--bind"); 
     exit(errno); 
} 
///*---Make it a "listening socket"---*/ 
    if (listen(sockfd, 20) != 0) 
    { 
     perror("socket--listen"); 
     exit(errno); 
    } 
//*---Forever... ---*/ 
    while (1) 
    { int clientfd; 
     struct sockaddr_in client_addr; 
     int addrlen=sizeof(client_addr); 
//*---accept a connection (creating a data pipe)---*/ 
     clientfd = accept(sockfd, (struct sockaddr*)&client_addr,&addrlen); 
//*---Echo back anything sent---*/ 
     recv(clientfd, buffer, MAXBUF, 0); 
     if (strcmp(buffer, "start\r\n")==0&&!thread){ 
         close(clientfd); 
         sleep(5); 
         time_date(); 
         pthread_t tid; 
         pthread_create(&tid,NULL,curl_thread,NULL); 
         thread=1; 
     } 
     if (strcmp(buffer, "stop\r\n")==0&&thread){   
         close(clientfd); 
         stop=1; 
         thread=0; 
         curl_global_cleanup(); 
     } 
     memset (buffer, '\0', MAXBUF); 
//*---Close data connection---*/ 
     close(clientfd); 
    } 
//---Clean up (should never get here!)---*/ 
    close(sockfd); 
    return 0; 
} 

信息一个开始/停止后:

HEAP SUMMARY: 
    in use at exit: 4,897 bytes in 58 blocks total heap usage: 2,987 allocs, 2,929 frees, 200,756 bytes allocated 576 bytes in 2 blocks are possibly lost in loss record 16 of 20 
    at 0x4C272B8: calloc (vg_replace_malloc.c:566) 
    by 0x401128E: _dl_allocate_tls (dl-tls.c:300) 
    by 0x4E36483: [email protected]@GLIBC_2.2.5 (allocatestack.c:580) 
    by 0x4016A2: main (in /root/test/testas) LEAK SUMMARY: 
    definitely lost: 0 bytes in 0 blocks 
    indirectly lost: 0 bytes in 0 blocks 
     possibly lost: 576 bytes in 2 blocks 

still reachable: 4,321 bytes in 56 blocks 
    suppressed: 0 bytes in 0 blocks 
Reachable blocks (those to which a pointer was found) are not shown. 
To see them, rerun with: --leak-check=full --show-reachable=yes 

For counts of detected and suppressed errors, rerun with: -v 
ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 12 from 6) 

谢谢你的帮助。

+0

我不确定它是否是你的内存泄漏的根本原因,但你的'write_data()'的返回值似乎不正确。在[fwrite](http://pubs.opengroup.org/onlinepubs/009695399/functions/fwrite.html)手册中,它提到返回值是写入元素的数量。但是从[curl](http://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html)手册中,它预期返回的字节数。实际的字节应该是'size * nmemb'。当然,如果'size'是1个字节的大小,上面的语句是没有意义的。 – SSC 2014-10-31 08:01:50

+0

完全不相关,但%02d可能是你想要做单sprintf()调用,而不是两个... – 2014-10-31 10:07:30

回答

0

这可能不会导致崩溃,但是您没有将正确的函数类型传递给pthread_create()。它应该是:

void * curl_thread(void* data) 
{ 
    ... 

您也永远不会加入该线程,每次创建新线程时都会泄露资源。请调用pthread_join()或pthread_detach()。

+0

谢谢! pthread_detach()解决了这个问题 – Seitan 2014-10-31 17:52:56