【问题标题】:c cleanup unused threadsc 清理未使用的线程
【发布时间】:2012-03-31 00:20:12
【问题描述】:

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

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)

【问题讨论】:

  • 你知道什么到底是内存泄漏吗?你是什​​么意思你不使用所有的线程?
  • 您的阵列中究竟存储了什么? (我感觉你过早地责怪而不是别的什么。)
  • 我知道我的程序正在泄漏内存,因为 valgrind 会打印泄漏消息。如示例代码 sn-p 所示,我没有创建和加入 2 个线程。结果是内存泄漏。
  • 有时会漏,有时不漏,不知道为什么
  • @xinghua,实际线程中发生了什么? (是否有对malloc 的调用而没有对free 的相应调用?)

标签: c memory-management memory-leaks pthreads


【解决方案1】:

pthread_exit 的使用“问题”。 This question 给出了一些细节,具体来说:

几个 glibc 函数在第一次调用时使用 malloc() 分配内存,它们在进程生命周期的剩余时间内一直分配内存。 glibc 不会费心在进程退出时释放此内存,因为它知道该进程无论如何都会被拆除 - 这只是浪费 CPU 周期。

所以这个内存泄漏很好。

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

【讨论】:

  • 非常感谢!!我终于修好了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-01
  • 2019-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
相关资源
最近更新 更多