Reputation: 149
I made an array of threads but I do not use all of them. it turn out to be a memory leak. Is there any function that I could use to free the memory?
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;
}
The code I used for experiment is here. I make it use more thread than I want to. if I don't add the 10 more threads, there will be no leak at all. it takes some text files as argument compile and run with
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);
}
here is what valgrind prints when I run the program. The memory leak is from the function I create the unused threads. somethimes it prints this message, sometimes it does not.
==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)
Upvotes: 1
Views: 2011
Reputation: 102096
The "problem" the use of pthread_exit
. This question gives some details, specifically:
Several glibc functions allocate memory with malloc() the first time they're called, which they keep allocated for the remainder of the process lifetime. glibc doesn't bother to free this memory at process exit, since it knows that the process is being torn down anyway - it'd just be a waste of CPU cycles.
So this memory leak is fine.
However, to actually get rid of the valgrind messages, you can use return NULL;
in place of pthread_exit(NULL);
on the last line of countLines
, since you are just returning from the start routine.
Upvotes: 3