c очистить неиспользуемые темы - PullRequest
0 голосов
/ 31 марта 2012

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

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 потоков, утечки вообще не будет. в качестве аргумента используются текстовые файлы скомпилируйте и запустите

gcc -g -Wall -pthread test.c valgrind --tool = memcheck --leak-check = полный --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 Ответ

2 голосов
/ 31 марта 2012

«Проблема» использования pthread_exit. Этот вопрос дает некоторые подробности, а именно:

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

Так что утечка памятинормально.

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

...