constexpr 与 C 中内存泄漏的关系

问题描述 投票:0回答:2

我正在学习 C,今天我写了一些代码将罗马数字转换为数字。

在我的程序中,我在

const int MAXWORTLEN = 16;
内部有一个
int main()
,以及一个布尔值数组,我已经声明了:
bool *vorzeichen = calloc(MAXWORTLEN, sizeof(bool));
,最后我
free()

我正在 CLion 中编程,有时会提供一些小提示来“改进”程序,例如将

int
变成
const int
(如果适合的话)。它还会警告内存泄漏、无法访问的代码等。

通过将我的

MAXWORTLEN
保留为
const int
,CLion 警告说
"Allocated memory is leaked"
。如其所示,通过更改为
constexpr int MAXWORTLEN = 16;
,警告就会消失。

Clion 给出的所有警告是:

Function 'main' always returns 0 :22
Allocated memory is leaked :29
Leak of memory allocated in function 'main' :33
Variable 'MAXWORTLEN' can be made constexpr :23

该文件是.c 文件。我使用构建工具 ninja 和 gcc 作为 C 编译器。

#include <stdio.h>
#include <stdlib.h>

int rom_wert(char c) {

    if(c>='a' && c<='z') {
        c = c + ('A' - 'a');
    }
    switch (c) {
        case 'I': return 1;
        case 'V': return 5;
        case 'X': return 10;
        case 'L': return 50;
        case 'C': return 100;
        case 'D': return 500;
        case 'M': return 1000;

        default: return -1;
    }
}

int main() {
    constexpr int MAXWORTLEN = 16;
    printf("Eingabe: ");

    char *eingabe = calloc(MAXWORTLEN, sizeof(char));
    scanf("%15s", eingabe);

    bool *vorzeichen = calloc(MAXWORTLEN, sizeof(bool));

    for(int i=0; eingabe[i] != '\0'; i++) {
        if(rom_wert(eingabe[i]) == -1) {
            return 0;
        }
        if(rom_wert(eingabe[i]) < rom_wert(eingabe[i+1])) {
            vorzeichen[i] = true;
        }
    }

    int summe = 0;
    for(int j=0; eingabe[j] != '\0'; j++) {
        if(vorzeichen[j] == 1)
            summe = summe - rom_wert(eingabe[j]);
        else if(vorzeichen[j] == 0)
            summe = summe + rom_wert(eingabe[j]);
    }

    printf("Ausgabe: %d", summe);

    free(eingabe);
    free(vorzeichen);

    return 0;
}                                           

原代码中内存泄漏在哪里,

constexpr
是如何解决的? 非常感谢任何答案,因为我在这个练习中的唯一目标是学习:)

c memory-management memory-leaks constexpr
2个回答
2
投票

原代码内存泄漏在哪里

内存泄漏发生在 main 顶部附近的 for 循环中执行

return 0
行时。
return 0
意味着该函数的其余部分永远不会执行,因此永远不会调用
free()
。 (在具有资源跟踪的现代操作系统上,这并不重要,因为程序随后退出并且所有内存都会自动释放,但从技术上讲它仍然是泄漏)

constexpr 如何解决它?

我不认为如此,但我怀疑用

constexpr
标记变量可能允许编译器/优化器隐式删除
calloc()
free()
调用并用基于堆栈的 char 替换它们相反,在这种情况下,不会出现内存泄漏,因为一开始就没有任何堆分配。


0
投票

原代码内存泄漏在哪里

如果这段代码片段中的

return
...

        if(rom_wert(eingabe[i]) == -1) {
            return 0;
        }

... 被执行,然后控制离开

main()
,而没有释放任何已分配的块。 这大概就是 CLion 所抱怨的,尽管在大多数操作环境中,这种特殊的“泄漏”是良性的:操作系统通常会在程序终止时清理仍然分配的任何内存。

constexpr
如何解决?

将变量声明为

constexpr
并不能解决这个问题。 我无法解释为什么 CLion 会影响 CLion 是否呈现诊断。 此外,我不能说我很关心 CLion 将
MAXWORTLEN
声明为
constexpr
的建议。 这样做不会产生我认为有什么特别的优势,并且会降低程序与旧版 C 编译器的兼容性,因为
constexpr
直到几周前才发布的 C23 才被引入标准 C..

© www.soinside.com 2019 - 2024. All rights reserved.