繁体   English   中英

如何在我的 C 程序中防止当前的 memory 泄漏?

[英]How can I prevent the current memory leaks in my C program?

我有一个程序,我将文本文件中的数据加载到结构数组中。 我的结构如下所示:

typedef struct A {
    int id;
    char* name;
    char* desc;
} A;

我开始从我的主 function 加载文件:

int main(void) {
    A* a;
    int* length = 0;
    arr = betolt("name.txt", &length);
    ...
    free(arr);

    return 0;
}

然后 - 在不同的 header 文件中 - 真正的逻辑是这样发生的:

A* load(char* file_name, int* length) {
    FILE* fp = fopen(file_name, "r");
    if (fp == NULL) return NULL;
    size_t ar_length = 500;
    size_t line_counter = 0;
    char** lines = malloc(ar_length);
    char line[256];
    while (fgets(line, sizeof(line), fp)) {
        lines[line_counter] = malloc(256);
        strcpy(lines[line_counter], line);
        line_counter++;
        if(line_counter > sizeof(lines)){
            ar_length *= 2;
            lines = realloc(lines, ar_length);
        }
    }
    *length = line_counter;
    fclose(fp);
    return process(lines, line_counter);
}

A* process(char** lines, int length) {
    A* arr = (A*) malloc(length * sizeof(A));
    for (int i = 0; i < length; ++i) {
        char* line = lines[i];
        char* ptr = strtok(line, ";");
        A a;
        a.id = i;
        int j = 0;
        while (ptr != NULL) {
            if (j == 0) {
                a.name = ptr;
            } else if (j == 1) {
                a.desc = ptr;
            }
            j++;
            ptr = strtok(NULL, ";");
        }
        arr[i] = a;
    }
    return arr;
}

我的程序工作得很好,但是,由于malloc(256)的原因,每条加载的行都有 memory 泄漏,并且在使用realloc(lines, ar_length); 我很不确定为什么会出现这些泄漏,因为它不应该在 function 运行后“自动释放” memory 吗? 如何修复这些 memory 泄漏? 提前致谢。

您的代码存在几个一般性问题。

  1. malloc 的铸造结果被认为是不好的做法。 有关详细信息,请参阅
  2. Realloc 可能会失败并返回 NULL 而不释放原始指针,您没有考虑到它。 更好的方法是 +- 这个:
int* x = malloc(200*sizeof(int));
//whatever
int* bigger_x = realloc(x, 400*sizeof(int));
if(bigger_x) x = bigger_x;
else handle_error("realloc");

至于更具体到您的问题和问题的要点:

  1. 我很不确定为什么会出现这些泄漏,因为它不应该在 function 运行后“自动释放” memory 吗? 如何修复这些 memory 泄漏?

不,这不对。 一般来说,一旦你完成使用它,你应该清理使用过的 memory。 什么时候? 好问题;)请注意,您正在使用指向动态分配数组的指针,例如: a.desc = ptr; . 一个简单的解决方案是复制每个字符串,即a.desc = strdup a.desc = strdup(ptr); , 然后process()返回后的空闲lines 请注意,您的strdup实际上确实分配了,因此您需要在使用完它们后释放它分配的资源。

  1. 使用 valgrind 或地址消毒剂。 只需使用调试符号和-fsanitize=address进行编译,这将为您提供大量有关泄漏内容和位置的信息。 clang 和 gcc 的现代版本支持它。 Valgrind 也是 go 的一种方式,但恕我直言,它不太方便。

加分项:C 没有 RAII,但无论如何您都可以使用一些基本的“范围保护”技术。 考虑以下代码:

char* buffer = malloc(300);
if(buffer) {
//do whatever
}
free(buffer);

如果你最后忘记了free() ,你就会有一个 memleak。 您可以做的是以稍微有创意的方式使用 for 循环来引入“范围保护”:

for(char* buffer = malloc(300); buffer; free(buffer), buffer=NULL)
{
  //do stuff
}

类似的技术也应该适用于FILE*和其他资源,或者可以使用宏进行概括,由您决定是否喜欢。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM