malloc - C memory leak warning - Stack Overflow

时间: 2025-01-06 admin 业界
#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 = (int*) malloc(sizeof(int));
    |      |                    ^~~~~~~~~~~~~~~~~~~
    |      |                    |
    |      |                    (1) allocated here
    |    9 | 
    |   10 |     ***new = 2137;
    |      |       ~~~~          
    |      |       |
    |      |       (2) ‘malloc(4)’ leaks here; was allocated at (1)
    |
2137

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?

#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 = (int*) malloc(sizeof(int));
    |      |                    ^~~~~~~~~~~~~~~~~~~
    |      |                    |
    |      |                    (1) allocated here
    |    9 | 
    |   10 |     ***new = 2137;
    |      |       ~~~~          
    |      |       |
    |      |       (2) ‘malloc(4)’ leaks here; was allocated at (1)
    |
2137

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?

Share Improve this question edited 23 hours ago Chris 36.1k5 gold badges31 silver badges53 bronze badges asked 23 hours ago Julian ZalewskiJulian Zalewski 1631 silver badge6 bronze badges New contributor Julian Zalewski is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 9
  • You shouldn't really cast the result of malloc. – Some programmer dude Commented 23 hours ago
  • 1 Welcome! Please don't make rolling changes to the code in response to (and which invalidate) comments, only change the post if it wasn't the code you actually use. – Weather Vane Commented 23 hours ago
  • To me, the code looks fine, with or without casts. Looks as if gcc is mistaken. Does that only happen with three indirections? – Peter - Reinstate Monica Commented 23 hours ago
  • It appears that the -fanalyzer option is buggy. If you remove that and run the code, there are no memory errors printed by the sanitizer. – Brad Lanam Commented 23 hours ago
  • 2 Possibly relevant reading: wiki.c2.com/?ThreeStarProgrammer – Chris Commented 23 hours ago
 |  Show 4 more comments

1 Answer 1

Reset to default 17

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.

最新文章