2014-10-31 129 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