내 코드의 이상한 동작을 파악하는 데 문제가 있습니다. 기본적으로 프로그램은 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)
감사합니다.
메모리 누수의 근본 원인이 확실하지 않지만'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
완전히 관련이 없지만 % 02d는 두 가지 대신 단일 sprintf() 호출을 수행하려고 할 것입니다. –