When I try recursively traverse directories in fork.Fork causing memory leak.İf I do just fork everythink okey but when I called function in child process I see memory leak on valgrind.I think ,I close every directory.But valgrind says opendir_tail.I tried write clodir in parent but then I take 1 allocated but 2 free error.Where is the problem ?
Here my code.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <ctype.h>
int dfsdirectory (char *path){
DIR* dir;
struct dirent *dirEntry;
struct stat fileStat;
char _PathN[1000];
int totalSize=0;
if (!(dir = opendir(path))){
closedir(dir);
return -1;
}
while ( ((dirEntry=readdir(dir)) != 0) ) {
int dirSize=0;
if (strcmp(dirEntry->d_name, ".") == 0
|| strcmp(dirEntry->d_name, "..") == 0)
continue;
snprintf(_PathN, sizeof(_PathN), "%s/%s", path, dirEntry->d_name);
lstat (_PathN, &fileStat);
if (S_ISDIR(fileStat.st_mode)){
int PID = fork();
if(PID<0){
closedir(dir);
return -1;
}
if(PID == 0){
dfsdirectory(_PathN);
while ((closedir(dir) == -1) && (errno == EINTR));
exit(0);
}
else{
wait(NULL);
}
}
}
closedir(dir);
return totalSize;
}
int main() {
dfsdirectory("A");
}
And valgrind output
==4070== Memcheck, a memory error detector
==4070== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==4070== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright
info
==4070== Command: ./main
==4070== Parent PID: 953
==4070==
==4072==
==4072== HEAP SUMMARY:
==4072== in use at exit: 32,816 bytes in 1 blocks
==4072== total heap usage: 3 allocs, 2 frees, 98,448 bytes allocated
==4072==
==4072== 32,816 bytes in 1 blocks are still reachable in loss record 1 of 1
==4072== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==4072== by 0x4EEB813: __alloc_dir (opendir.c:247)
==4072== by 0x4EEB902: opendir_tail (opendir.c:145)
==4072== by 0x108977: dfsdirectory (in /home/alex/Desktop/main)
==4072== by 0x108AE6: main (in /home/alex/Desktop/main)
==4072==
==4072== LEAK SUMMARY:
==4072== definitely lost: 0 bytes in 0 blocks
==4072== indirectly lost: 0 bytes in 0 blocks
==4072== possibly lost: 0 bytes in 0 blocks
==4072== still reachable: 32,816 bytes in 1 blocks
==4072== suppressed: 0 bytes in 0 blocks
==4072==
==4072== For counts of detected and suppressed errors, rerun with: -v
==4072== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==4071==
==4071== HEAP SUMMARY:
==4071== in use at exit: 0 bytes in 0 blocks
==4071== total heap usage: 2 allocs, 2 frees, 65,632 bytes allocated
==4071==
==4071== All heap blocks were freed -- no leaks are possible
==4071==
==4071== For counts of detected and suppressed errors, rerun with: -v
==4071== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==4075==
==4075== HEAP SUMMARY:
==4075== in use at exit: 65,632 bytes in 2 blocks
==4075== total heap usage: 4 allocs, 2 frees, 131,264 bytes allocated
==4075==
==4075== 32,816 bytes in 1 blocks are still reachable in loss record 1 of 2
==4075== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==4075== by 0x4EEB813: __alloc_dir (opendir.c:247)
==4075== by 0x4EEB902: opendir_tail (opendir.c:145)
==4075== by 0x108977: dfsdirectory (in /home/alex/Desktop/main)
==4075== by 0x108AE6: main (in /home/alex/Desktop/main)
==4075==
==4075== 32,816 bytes in 1 blocks are still reachable in loss record 2 of 2
==4075== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==4075== by 0x4EEB813: __alloc_dir (opendir.c:247)
==4075== by 0x4EEB902: opendir_tail (opendir.c:145)
==4075== by 0x108977: dfsdirectory (in /home/alex/Desktop/main)
==4075== by 0x108A78: dfsdirectory (in /home/alex/Desktop/main)
==4075== by 0x108AE6: main (in /home/alex/Desktop/main)
==4075==
==4075== LEAK SUMMARY:
==4075== definitely lost: 0 bytes in 0 blocks
==4075== indirectly lost: 0 bytes in 0 blocks
==4075== possibly lost: 0 bytes in 0 blocks
==4075== still reachable: 65,632 bytes in 2 blocks
==4075== suppressed: 0 bytes in 0 blocks
==4075==
==4075== For counts of detected and suppressed errors, rerun with: -v
==4075== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==4076==
==4076== HEAP SUMMARY:
==4076== in use at exit: 65,632 bytes in 2 blocks
==4076== total heap usage: 4 allocs, 2 frees, 131,264 bytes allocated
==4076==
==4076== 32,816 bytes in 1 blocks are still reachable in loss record 1 of 2
==4076== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==4076== by 0x4EEB813: __alloc_dir (opendir.c:247)
==4076== by 0x4EEB902: opendir_tail (opendir.c:145)
==4076== by 0x108977: dfsdirectory (in /home/alex/Desktop/main)
==4076== by 0x108AE6: main (in /home/alex/Desktop/main)
==4076==
==4076== 32,816 bytes in 1 blocks are still reachable in loss record 2 of 2
==4076== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==4076== by 0x4EEB813: __alloc_dir (opendir.c:247)
==4076== by 0x4EEB902: opendir_tail (opendir.c:145)
==4076== by 0x108977: dfsdirectory (in /home/alex/Desktop/main)
==4076== by 0x108A78: dfsdirectory (in /home/alex/Desktop/main)
==4076== by 0x108AE6: main (in /home/alex/Desktop/main)
==4076==
==4076== LEAK SUMMARY:
==4076== definitely lost: 0 bytes in 0 blocks
==4076== indirectly lost: 0 bytes in 0 blocks
==4076== possibly lost: 0 bytes in 0 blocks
==4076== still reachable: 65,632 bytes in 2 blocks
==4076== suppressed: 0 bytes in 0 blocks
==4076==
==4076== For counts of detected and suppressed errors, rerun with: -v
==4076== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==4074==
==4074== HEAP SUMMARY:
==4074== in use at exit: 32,816 bytes in 1 blocks
==4074== total heap usage: 3 allocs, 2 frees, 98,448 bytes allocated
==4074==
==4074== 32,816 bytes in 1 blocks are still reachable in loss record 1 of 1
==4074== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==4074== by 0x4EEB813: __alloc_dir (opendir.c:247)
==4074== by 0x4EEB902: opendir_tail (opendir.c:145)
==4074== by 0x108977: dfsdirectory (in /home/alex/Desktop/main)
==4074== by 0x108AE6: main (in /home/alex/Desktop/main)
==4074==
==4074== LEAK SUMMARY:
==4074== definitely lost: 0 bytes in 0 blocks
==4074== indirectly lost: 0 bytes in 0 blocks
==4074== possibly lost: 0 bytes in 0 blocks
==4074== still reachable: 32,816 bytes in 1 blocks
==4074== suppressed: 0 bytes in 0 blocks
==4074==
==4074== For counts of detected and suppressed errors, rerun with: -v
==4074== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==4073==
==4073== HEAP SUMMARY:
==4073== in use at exit: 0 bytes in 0 blocks
==4073== total heap usage: 2 allocs, 2 frees, 65,632 bytes allocated
==4073==
==4073== All heap blocks were freed -- no leaks are possible
==4073==
==4073== For counts of detected and suppressed errors, rerun with: -v
==4073== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==4070==
==4070== HEAP SUMMARY:
==4070== in use at exit: 0 bytes in 0 blocks
==4070== total heap usage: 1 allocs, 1 frees, 32,816 bytes allocated
==4070==
==4070== All heap blocks were freed -- no leaks are possible
==4070==
==4070== For counts of detected and suppressed errors, rerun with: -v
==4070== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
This memory leak is related to the recursion. You do not close the directory handles further up the stack:
==4075== by 0x4EEB902: opendir_tail (opendir.c:145)
==4075== by 0x108977: dfsdirectory (in /home/alex/Desktop/main)
==4075== by 0x108AE6: main (in /home/alex/Desktop/main)
==4075== by 0x4EEB902: opendir_tail (opendir.c:145)
==4075== by 0x108977: dfsdirectory (in /home/alex/Desktop/main)
==4075== by 0x108A78: dfsdirectory (in /home/alex/Desktop/main)
==4075== by 0x108AE6: main (in /home/alex/Desktop/main)
It is a leak of the still reachable kind, and these can be harmless, either because you call exit
early (which applies here), or because they refer to data structures that are rooted in global variables. There is considerable disagreement among C developers whether these leaks need to be addressed, or whether it is acceptable to leave them in a program.
Please also note that the EINTR
check for closedir
is wrong with glibc. It introduces a double-free vulnerability in case of an EINTR
failure.