2012-03-31 7 views
0

Я создал массив потоков, но я не использую их все. он оказывается утечкой памяти. Есть ли какая-нибудь функция, которую я мог бы использовать для освобождения памяти?c cleanup unused threads

void func(args...) 
{ 
. 
. 
. 
pthread_t threads[10] 

int i; 
for(i = 0; i < 8; i++) 
{ 
    /* create 8 threads */ 
} 
for(i = 0; i < 8; i++) 
{ 
    /* join 8 threads */ 
} 
. 
. 
. 
return; 
} 

Код, который я использовал для эксперимента, приведен здесь. Я использую больше потоков, чем хочу. если я не добавлю еще 10 потоков, утечки вообще не будет. он принимает некоторые текстовые файлы в качестве аргумента компиляции и запуска с

НКУ -g -Wall -pthread test.c Valgrind --tool = MemCheck --leak-чек = полный --show достижимым = да ./a .out * .txt

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <fcntl.h> 
#include <unistd.h> 

#define DEBUG 0 
#define BUFLEN 10000 

/* function declaration */ 
static void* countLines(void* input); 
static void error(const char*); 

/* global variable */ 
static int total_th; /* total number of threads */ 
static int count_th; /* the count of the finished threads */ 

/* 
* main starts here 
*/ 
int main(int argc, char** argv) 
{ 
    /* if there is no command line arguments, print error */ 
    if(argc < 2) 
    { 
     error("there should be at lease one argument!\n"); 
     exit(-1); 
    } 

    /* initialize thread counters */ 
    total_th = argc - 1; 
    count_th = 0; 

    pthread_t pt[ total_th + 10]; /* the ptreads to read file lines */ 

    /* create threads for each file */ 
    int i; 
    for(i = 0; i < total_th; i++) 
    { 
     if((pthread_create(&pt[i], NULL, 
       countLines, (void*) argv[i + 1])) != 0) 
     { 
      fprintf(stderr, "error in thread create\n"); 
     } 
    } 

    /* main thread wait for all the slaves to finish */ 
    for(i = 0; i < total_th; i++) 
    { 
     if(pthread_join(pt[i], NULL) != 0) 
      fprintf(stderr, "error in thread join\n"); 
    } 

    return(0); 
} 

/** 
* void* countLines(void * input) 
* @param input: the name of the file 
* @return NULL 
* count the number of lines for the specified file 
*/ 
void* countLines(void * input) 
{ 
    char* fileName = (char*) input; /* file name */ 
    int newLineCount = 0; /* a count of the new line character */ 
    int fd; /*file descriptor*/ 

    /* open file, if open fail print error message */ 
    if((fd = open(fileName, O_RDONLY)) == -1) 
    { 
     fprintf(stderr, "Can not open file - %s\n", fileName); 
     count_th++; 
     return NULL; 
    } 

    char buf[BUFLEN]; /* the buffer to be read */ 
    int lastRead; /* the number of characters read to buffer */ 

    /* read the file */ 
    while((lastRead = read(fd, buf, BUFLEN))) 
    { 
     /* detect error state */ 
     if(lastRead == -1) 
     { 
      fprintf(stderr, "error reading file %s!\n", fileName); 
      count_th++; 
      return NULL; 
     } 

     /* count the new line character */ 
     int i; 
     for(i = 0; i < lastRead; i++) 
     { 
      if(buf[i] == '\n') 
      { 
       newLineCount++; 
      } 
     } 
    } 

    printf("There are %d lines in %s\n", newLineCount, fileName); 

    close(fd); /* close file descriptor */ 
    pthread_exit(NULL); 
} 

/** 
* void error(const char*str) 
* @param str error message 
* print an error message 
*/ 
void error(const char *str) 
{ 
    perror(str); 
    exit(-1); 
} 

вот что печатает Valgrind при запуске программы. Утечка памяти связана с функцией, которую я создаю неиспользуемые потоки. что-то печатает это сообщение, иногда это не так.

==4737== 
==4737== HEAP SUMMARY: 
==4737==  in use at exit: 1,590 bytes in 5 blocks 
==4737== total heap usage: 12 allocs, 7 frees, 3,494 bytes allocated 
==4737== 
==4737== 36 bytes in 1 blocks are still reachable in loss record 1 of 5 
==4737== at 0x4C28F9F: malloc (vg_replace_malloc.c:236) 
==4737== by 0x40085BF: _dl_map_object (dl-load.c:162) 
==4737== by 0x4012B79: dl_open_worker (dl-open.c:226) 
==4737== by 0x400E9C5: _dl_catch_error (dl-error.c:178) 
==4737== by 0x40133A9: _dl_open (dl-open.c:569) 
==4737== by 0x516AF6F: do_dlopen (dl-libc.c:86) 
==4737== by 0x400E9C5: _dl_catch_error (dl-error.c:178) 
==4737== by 0x516B029: __libc_dlopen_mode (dl-libc.c:47) 
==4737== by 0x4E3F75B: pthread_cancel_init (unwind-forcedunwind.c:53) 
==4737== by 0x4E3F91B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126) 
==4737== by 0x4E3D9DF: __pthread_unwind (unwind.c:130) 
==4737== by 0x4E380A4: pthread_exit (pthreadP.h:265) 
==4737== 
==4737== 36 bytes in 1 blocks are still reachable in loss record 2 of 5 
==4737== at 0x4C28F9F: malloc (vg_replace_malloc.c:236) 
==4737== by 0x400B43C: _dl_new_object (dl-object.c:164) 
==4737== by 0x4006575: _dl_map_object_from_fd (dl-load.c:967) 
==4737== by 0x400831E: _dl_map_object (dl-load.c:2260) 
==4737== by 0x4012B79: dl_open_worker (dl-open.c:226) 
==4737== by 0x400E9C5: _dl_catch_error (dl-error.c:178) 
==4737== by 0x40133A9: _dl_open (dl-open.c:569) 
==4737== by 0x516AF6F: do_dlopen (dl-libc.c:86) 
==4737== by 0x400E9C5: _dl_catch_error (dl-error.c:178) 
==4737== by 0x516B029: __libc_dlopen_mode (dl-libc.c:47) 
==4737== by 0x4E3F75B: pthread_cancel_init (unwind-forcedunwind.c:53) 
==4737== by 0x4E3F91B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126) 
==4737== 
==4737== 56 bytes in 1 blocks are still reachable in loss record 3 of 5 
==4737== at 0x4C28F9F: malloc (vg_replace_malloc.c:236) 
==4737== by 0x400D187: _dl_map_object_deps (dl-deps.c:505) 
==4737== by 0x4012BD6: dl_open_worker (dl-open.c:263) 
==4737== by 0x400E9C5: _dl_catch_error (dl-error.c:178) 
==4737== by 0x40133A9: _dl_open (dl-open.c:569) 
==4737== by 0x516AF6F: do_dlopen (dl-libc.c:86) 
==4737== by 0x400E9C5: _dl_catch_error (dl-error.c:178) 
==4737== by 0x516B029: __libc_dlopen_mode (dl-libc.c:47) 
==4737== by 0x4E3F75B: pthread_cancel_init (unwind-forcedunwind.c:53) 
==4737== by 0x4E3F91B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126) 
==4737== by 0x4E3D9DF: __pthread_unwind (unwind.c:130) 
==4737== by 0x4E380A4: pthread_exit (pthreadP.h:265) 
==4737== 
==4737== 288 bytes in 1 blocks are still reachable in loss record 4 of 5 
==4737== at 0x4C279F2: calloc (vg_replace_malloc.c:467) 
==4737== by 0x4010359: _dl_check_map_versions (dl-version.c:300) 
==4737== by 0x4012EF0: dl_open_worker (dl-open.c:269) 
==4737== by 0x400E9C5: _dl_catch_error (dl-error.c:178) 
==4737== by 0x40133A9: _dl_open (dl-open.c:569) 
==4737== by 0x516AF6F: do_dlopen (dl-libc.c:86) 
==4737== by 0x400E9C5: _dl_catch_error (dl-error.c:178) 
==4737== by 0x516B029: __libc_dlopen_mode (dl-libc.c:47) 
==4737== by 0x4E3F75B: pthread_cancel_init (unwind-forcedunwind.c:53) 
==4737== by 0x4E3F91B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126) 
==4737== by 0x4E3D9DF: __pthread_unwind (unwind.c:130) 
==4737== by 0x4E380A4: pthread_exit (pthreadP.h:265) 
==4737== 
==4737== 1,174 bytes in 1 blocks are still reachable in loss record 5 of 5 
==4737== at 0x4C279F2: calloc (vg_replace_malloc.c:467) 
==4737== by 0x400B1CD: _dl_new_object (dl-object.c:77) 
==4737== by 0x4006575: _dl_map_object_from_fd (dl-load.c:967) 
==4737== by 0x400831E: _dl_map_object (dl-load.c:2260) 
==4737== by 0x4012B79: dl_open_worker (dl-open.c:226) 
==4737== by 0x400E9C5: _dl_catch_error (dl-error.c:178) 
==4737== by 0x40133A9: _dl_open (dl-open.c:569) 
==4737== by 0x516AF6F: do_dlopen (dl-libc.c:86) 
==4737== by 0x400E9C5: _dl_catch_error (dl-error.c:178) 
==4737== by 0x516B029: __libc_dlopen_mode (dl-libc.c:47) 
==4737== by 0x4E3F75B: pthread_cancel_init (unwind-forcedunwind.c:53) 
==4737== by 0x4E3F91B: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126) 
==4737== 
==4737== LEAK SUMMARY: 
==4737== definitely lost: 0 bytes in 0 blocks 
==4737== indirectly lost: 0 bytes in 0 blocks 
==4737==  possibly lost: 0 bytes in 0 blocks 
==4737== still reachable: 1,590 bytes in 5 blocks 
==4737==   suppressed: 0 bytes in 0 blocks 
==4737== 
==4737== For counts of detected and suppressed errors, rerun with: -v 
==4737== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4) 
+1

Знаете ли вы, что * точно утечка памяти? Что вы имеете в виду, что не используете все потоки? – Chris

+0

Что именно вы храните в своем массиве? (У меня такое чувство, что вы преждевременно обвиняете _it_, а не что-то еще.) – sarnold

+0

Я знаю, что моя программа утечки памяти, потому что valgrind печатает сообщение об утечке. как показывает фрагмент кода кода, я не создал и не присоединился к двум потокам. он оказывается утечкой памяти. – xinghua

ответ

2

"Проблема" использование pthread_exit. This question дает некоторые детали, а именно:

Несколько Glibc функции выделения памяти с таНос() в первый раз они называются, что они продолжают направляемой на оставшуюся часть жизни процесса. glibc не утруждает себя освобождением этой памяти при выходе процесса, поскольку он знает, что процесс все равно срывается - это просто пустая трата циклов процессора.

Так что эта утечка памяти в порядке.

Однако, на самом деле избавиться от VALGRIND сообщений, вы можете использовать return NULL; вместо pthread_exit(NULL); на последней строке countLines, так как вы только что вернулся с самого начала дня.

+0

Спасибо вам большое! Я, наконец, исправлю это. – xinghua