Valgrind does not report a memory leak during my actual usage, only during my scripted test that I scripted with a shell script to test my own shell. I found that I didn't have to use malloc
every time I did. For example, strdup
could do it for me. Now I wonder if it is possible to formally prove that I really need malloc where I use it or can I make an analysis and either prove or disprove that malloc
is actually needed?
If I can rewrite the program so that it doesn't use malloc then I'd be glad. I'd be even happier if I can prove for certain cases that I don't need malloc, since there were cases were I only had to free()
and malloc size was done automatically. One error message that appears only during test is the following.
.
==29846== Memcheck, a memory error detector
==29846== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==29846== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==29846== Command: ./shell
==29846==
'PATH' is set to /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin.
stdin is a file or a pipe
==29846==
==29846== HEAP SUMMARY:
==29846== in use at exit: 83,052 bytes in 171 blocks
==29846== total heap usage: 240 allocs, 69 frees, 101,754 bytes allocated
==29846==
==29846== 12 bytes in 1 blocks are definitely lost in loss record 5 of 93
==29846== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==29846== by 0x50FCA59: strdup (strdup.c:42)
==29846== by 0x4E57624: readline (in /usr/lib/x86_64-linux-gnu/libedit.so.2.0.53)
==29846== by 0x40193B: main (main.c:599)
==29846==
==29846== LEAK SUMMARY:
==29846== definitely lost: 12 bytes in 1 blocks
==29846== indirectly lost: 0 bytes in 0 blocks
==29846== possibly lost: 0 bytes in 0 blocks
==29846== still reachable: 83,040 bytes in 170 blocks
==29846== suppressed: 0 bytes in 0 blocks
==29846== Reachable blocks (those to which a pointer was found) are not shown.
==29846== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==29846==
==29846== For counts of detected and suppressed errors, rerun with: -v
==29846== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
The test I scripted is:
#!/bin/sh
echo "-- Testing our implementation of OpenShell --"
echo ""
echo "- If you have any problem in passing a test read the corresponding"
echo "- source file to understand what the test is checking"
echo ""
printf "********************* PRESS ENTER TO RUN TESTS ... "
read _
# Key pressed, do something
printf "********************* TEST WILDCARDS \n***** Press any key to listing all files in current directory... "
read _
valgrind --leak-check=full --leak-kinds=all./shell << EOF
ls -al *.*
EOF
printf "********************* TEST ALGORITHMS ... "
read _
echo "top -b -n1|head -8|tail -1" | ./shell
printf "********************* TEST ALGORITHMS Part II. ... "
read _
valgrind --leak-check=full --leak-kinds=all ./shell << EOF
who|awk '{print \$4 ; print \$3}'|sort -n|wc -l
EOF
printf "********************* TEST CHECKENV. ... "
read _
valgrind --leak-check=full --leak-kinds=all ./shell << EOF
checkenv
EOF
printf "********************* TEST DONE. YOU SHOULD SEE OUTPUT FROM TEST ABOVE ... "
read _
My offending code is here:
while (1) {
buf = "> ";
if (!isatty(fileno(stdin))) {
printf("stdin is a file or a pipe\n");
if (buf)
command(readline(buf));
exit(0);
}
cwd = malloc(sizeof(char *) * 100);
if (cwd != NULL && getcwd(cwd, 99) == cwd) {
printf("%s: ", cwd);
char *input = readline(buf);
add_history(input);
command(input);
free(input);
free(cwd);
} else {
printf("%s: ", getenv("USER"));
char *input = readline(buf);
add_history(input);
if (input) {
command(input);
free(input);
}
}
}
malloc
isENOMEM
?strdup
: "The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(3), and can be freed with free(3).". So you still need malloc.free
right? I mean it's not like youmalloc
new memory space when you doreadline
right?