簡體   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