c清理未使用的线程

时间:2012-03-31 00:20:12

标签: c memory-management memory-leaks pthreads

我创建了一个线程数组,但我没有使用它们。结果是内存泄漏。有什么功能可以用来释放内存吗?

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 = full --show-reachable = yes ./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 个答案:

答案 0 :(得分:2)

使用pthread_exit的“问题”。 This question提供了一些细节,特别是:

  

几个glibc函数在第一次调用malloc()时分配内存,它们在进程生命周期的剩余时间内保持分配。 glibc并不打算在进程退出时释放这个内存,因为它知道该进程正在被拆除 - 它只是浪费CPU周期。

所以这个内存泄漏很好。

但是,要真正摆脱valgrind消息,您可以在return NULL;的最后一行使用pthread_exit(NULL);代替countLines,因为您刚刚从启动例程返回