2014-10-31 2 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 바이트 크기라면 moot입니다. – SSC

+0

완전히 관련이 없지만 % 02d는 두 가지 대신 단일 sprintf() 호출을 수행하려고 할 것입니다. –

답변

0

이것은 크래시를 일으키지 않았지만 pthread_create()에 올바른 함수 유형을 전달하지 않습니다. 그것은이어야합니다 :

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

새 스레드를 만들 때마다 리소스를 유출하지 마십시오. pthread_join() 또는 pthread_detach()를 호출하십시오.

+0

감사합니다! pthread_detach()가 문제를 해결했습니다. – Seitan