#include <stdio.h>
#include <stdlib.h>
int main()
{
int ***new = malloc(sizeof(int **));
*new = malloc(sizeof(int *));
**new = malloc(sizeof(int));
***new = 2137;
printf("%i\n", ***new);
free(**new);
free(*new);
free(new);
return EXIT_FAILURE;
}
This code, when compiled using command gcc -Wall -Wextra -fanalyzer -g -O0 -fsanitize=address,undefined -o test2 test2.c
produces output:
test2.c: In function ‘main’:
test2.c:10:7: warning: leak of ‘malloc(4)’ [CWE-401] [-Wanalyzer-malloc-leak]
10 | ***new = 2137;
| ^~~~
‘main’: events 1-2
|
| 8 | **new = malloc(sizeof(int));
| | ^~~~~~~~~~~~~~~~~~~
| | |
| | (1) allocated here
| 9 |
| 10 | ***new = 2137;
| | ~~~~
| | |
| | (2) ‘malloc(4)’ leaks here; was allocated at (1)
|
I have narrowed down my code do something as simple as this, but still cannot find the problem. I know I am not checking malloc errors, doing so does not help, I have removed them to improve clarity. How do I fix this?
This is a bug in the analyzer. If we look closely at the output:
|
| 8 | **new = (int*) malloc(sizeof(int));
| | ^~~~~~~~~~~~~~~~~~~
| | |
| | (1) allocated here
| 9 |
| 10 | ***new = 2137;
| | ~~~~
| | |
| | (2) ‘malloc(4)’ leaks here; was allocated at (1)
We can see that the assigned pointer it's checking is not the same one where the leak happens. Specifically, it incorrectly thinks that an assignment to ***new
overwrites as assignment to **new
.
To verify, we can run the code through valgrind, which shows there is no memory leak:
==23502== Memcheck, a memory error detector
==23502== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==23502== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==23502== Command: ./x1
==23502==
2137
==23502==
==23502== HEAP SUMMARY:
==23502== in use at exit: 0 bytes in 0 blocks
==23502== total heap usage: 3 allocs, 3 frees, 20 bytes allocated
==23502==
==23502== All heap blocks were freed -- no leaks are possible
==23502==
==23502== For lists of detected and suppressed errors, rerun with: -s
==23502== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
When compiling with versions 10 and 11 of gcc with these options, no warnings appear. The warning you show start with version 12 of gcc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With