为什么GCC的静态分析器会错误地警告存储在已分配内存块中的指向已分配内存块本身的指针可能会泄漏?

问题描述 投票:0回答:1
#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;
}

使用命令

gcc -Wall -Wextra -fanalyzer -g -O0 -fsanitize=address,undefined -o test2 test2.c
编译此代码时会产生输出:

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)
    |

我已经缩小了我的代码范围,做了一些像这样简单的事情,但仍然找不到问题。我知道我没有检查 malloc 错误,这样做没有帮助,我已删除它们以提高清晰度。 我该如何解决这个问题?

c malloc
1个回答
23
投票

这是分析器中的一个错误。 如果我们仔细观察输出:

    |
    |    8 |     **new = (int*) malloc(sizeof(int));
    |      |                    ^~~~~~~~~~~~~~~~~~~
    |      |                    |
    |      |                    (1) allocated here
    |    9 | 
    |   10 |     ***new = 2137;
    |      |       ~~~~          
    |      |       |
    |      |       (2) ‘malloc(4)’ leaks here; was allocated at (1)

我们可以看到它正在检查的分配指针与发生泄漏的指针不同。 具体来说,它错误地认为对

***new
的赋值会覆盖对
**new
的赋值。

为了验证,我们可以通过valgrind运行代码,这表明没有内存泄漏:

==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)

使用这些选项使用 gcc 版本 10 和 11 进行编译时,不会出现警告。 您显示的警告从 gcc 版本 12 开始。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.