簡體   English   中英

為2d char數組動態分配內存

[英]Dynamically allocating memory for 2d char array

我使用malloc動態分配2d char數組。 除非我在free()之前將每個數組索引設置為NULL,否則在嘗試free()時會出現分段錯誤。 為什么我會出現分段錯誤?

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

int main(void) {

    int nrows = 20; int ncolumns = 10;
    char ** arr = malloc(nrows * sizeof(char *));
    for(int i = 0; i < nrows; i++)
        arr[i] = malloc(ncolumns * sizeof(char));

    arr[0] = "string1";
    arr[1] = "string2";

    // does not work without the following code:
    // for(int i = 0; i < 20; i++)
    //     arr[i] = NULL;

    for(int i = 0; i < 20; i++)
        free(arr[i]);
    free(arr);

    return 0;
}

當你這樣做:

arr[0] = "string1";
arr[1] = "string2";

覆蓋arr[0]arr[1] ,其中包含從malloc返回的malloc地址,以及兩個字符串常量的地址。 這會導致內存泄漏,因為內存不再可訪問。 這也是您在調用free時崩潰的原因,因為這些變量不再保留已分配內存的地址。

你可能想要做的就是使用strcpy ,它會將字符串文字的內容復制到你分配的內存中。

strcpy(arr[0], "string1");
strcpy(arr[1], "string2");

現在你可以正確free內存了。

您的代碼沒問題,問題來自於您在此處為數組指定字符串文字arr[0] = "string1";

因此,您正在使用指向字符串文字的指針替換指向已分配內存的arr[0]的指針。

對文字的指針受到保護,你不能釋放它們(也不能寫入它們),因為你沒有分配它們。

要解決此問題,請使用strcpy在已分配的內存中復制文字的值:

strcpy(arr[0], "string1");
strcpy(arr[1], "string2");

=運算符不復制它只分配指針的字符串。 因此,對於那些數組元素,您的malloced內存不再可訪問,並試圖釋放它是一個未定義的行為,可能會導致段錯誤。

您需要使用strcpy復制它。

有兩點需要了解:

  • 你的內存中有兩個區域(為了便於理解)堆和堆棧
  • malloc,realloc,calloc從堆分配ressource。 我只會說malloc(但它是一樣的)
    • free只能從堆中釋放ressource。 Stack是編譯器的reserver(它存儲函數調用和其他數據)

從malloc獲得的每個資源的規則你必須釋放它。 釋放只是調用自由函數(但我們可以選擇assigne空指針,以確保它被釋放)。

char * a = malloc(255);

免費

free(a);/* this is mandatory */
a = NULL;/* we can add this to the first line */

事實上,你習慣於分配NULL值,有一次你訪問它的值你會有NULL deference錯誤:所以你會知道在哪里找到錯誤

你嘗試做什么:分配一個數組char ** arr = malloc(nrows * sizeof(char *)); 你釋放它free(arr);

但你分配了20個char arr[i] = malloc(ncolumns * sizeof(char));數組arr[i] = malloc(ncolumns * sizeof(char)); 你忽略了它的值arr[0] = "string1"; (你松開了malloc返回的值,所以你現在不能釋放arr [0])我們不是在C ++中。 因此堆棧中存儲了“string1”(因此malloc無法釋放它)並且您可以免費調用它。

你可以做什么

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

int main(void) {

    int nrows = 20; int ncolumns = 10;
    char ** arr = malloc(nrows * sizeof(char *));
    for(int i = 0; i < nrows; i++)
        arr[i] = malloc(ncolumns * sizeof(char));
    free(arr[0]);//know we can loose it value because it is freed
    arr[0] = NULL;// in fact we assign a value just after so this line is useless but is educationnal purpose
    free(arr[1]);//know we can loose it value because it is freed
    arr[1] = NULL;// in fact we assign a value just after so this line is useless but is educationnal purpose
    arr[0] = "string1";
    arr[1] = "string2";

    // does not work without the following code:
    // for(int i = 0; i < 20; i++)
    //     arr[i] = NULL;

    for(int i = 2; i < 20; i++)//we start at 2 because the first two value are on the stack
    {
        free(arr[i]);
        arr[i] = NULL;//this is useless because we will free arr just after the loop)
    }
    free(arr);
    arr = NULL;// this is useless because we exit the end of program

    return 0;
}

free調用時崩潰是代碼中其他地方不正確的內存管理的標志。 當你將指針設置為NULL然后free它時,你不會崩潰,因為C標准§7.22.3.3保證free(NULL)是良性的:

7.22.3.3自由功能

...如果ptr是空指針,則不會發生任何操作 否則,如果參數與先前由內存管理函數返回的指針不匹配,或者如果通過調用free或realloc釋放了空間,則行為未定義。

強調我的。

至於其他的答案已經指出,您要撥打free上的內存,你沒有明確地分配malloc -家庭功能(因為你改寫arr[i]的指針指向字符串常量)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM