5

有人可能比我更聰明地向我解釋爲什麼下面的代碼段出錯?通過引用分配內存沒有問題,但只要我嘗試通過引用分配任何內容或釋放內存,就會發生段錯誤。二維動態數組的分配和傳遞參考C

我敢肯定,我錯過了一些關於指針和通過引用傳遞的基本概念,希望能夠拋棄一些光。

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

void allocateMatrix(float ***); 
void fillMatrix(float ***); 
void freeMatrix(float **); 

int main() { 
    float **matrix; 

    allocateMatrix(&matrix);  // this function calls and returns OK 
    fillMatrix(&matrix);   // this function will segfault 
    freeMatrix(matrix);    // this function will segfault 

    exit(0); 
} 

void allocateMatrix(float ***m) { 
    int i; 
    m = malloc(2*sizeof(float*)); 
    for (i = 0; i < 2; i++) { 
     m[i] = malloc(2*sizeof(float)); 
    } 
    return; 
} 

void fillMatrix(float ***m) { 
    int i,j; 
    for (i = 0; i < 2; i++) { 
     for (j = 0; j < 2; j++) { 
      (*m)[i][j] = 1.0;  // SEGFAULT 
     } 
    } 
    return; 
} 

void freeMatrix(float **m) { 
    int i; 
    for (i = 0; i < 2; i++) { 
     free(m[i]);     // SEGFAULT 
    } 
    free(m); 
    return; 
} 
+0

我其實有點驚訝,編譯。 「void allocateMatrix(&m)」可能不會像預期的那樣將m輸入爲float **。另外,C中的引用與C++中的引用不同。 – Corbin 2012-04-07 04:08:25

+0

爲什麼'freeMatrix'等簽名在聲明和定義時有所不同? – keety 2012-04-07 04:14:47

+0

keety,科爾賓:對不起復制粘貼失敗,修復它 – holocron 2012-04-07 04:37:43

回答

8

一組的問題是在這裏:

void allocateMatrix(float ***m) { 
    int i; 
    m = malloc(2*sizeof(float*)); 
    for (i = 0; i < 2; i++) { 
     m[i] = malloc(2*sizeof(float)); 
    } 
    return; 
} 

您需要分配到*m以將信息返回到調用代碼,並且您還需要在循環中分配給(*m)[i]

void allocateMatrix(float ***m) 
{ 
    *m = malloc(2*sizeof(float*)); 
    for (int i = 0; i < 2; i++) 
     (*m)[i] = malloc(2*sizeof(float)); 
} 

至少有一個機會,其他功能都可以。該fillMatrix()寫入和正確調用,雖然它可以通過指針失去第三*被簡化:

void fillMatrix(float **m) 
{ 
    for (int i = 0; i < 2; i++) 
    { 
     for (int j = 0; j < 2; j++) 
      m[i][j] = 1.0;   
    } 
} 

這可能是最好的三指針傳遞給freeMatrix(),這樣就可以在零的指針調用函數:

void freeMatrix(float ***m) 
{ 
    for (int i = 0; i < 2; i++) 
     free((*m)[i]); 
    free(*m); 
    *m = 0; 
} 

然後調用變爲:

allocateMatrix(&matrix); 
fillMatrix(matrix); 
freeMatrix(&matrix); 
+0

謝謝Jonathan,這非常有道理。 – holocron 2012-04-07 04:51:40

3

良好的間接使用。只是嘗試與格式一致。它提高了可讀性並減少了錯誤。例如

函數調用:

allocateMatrix &matrix 
    fillMatrix &matrix 
    freeMatrix &matrix 

聲明

void allocateMatrix float ***m 
void fillMatrix float ***m 
void freeMatrix float ***m 

處理

(*m)[i] = malloc(2 * sizeof(float)) 
    (*m)[i][j] = 1.0 
    free (*m)[i] 
+0

這是有道理的,我現在試着實現。 – holocron 2012-04-07 04:50:48

0

從你的樂趣指針返回ction可能是更好的分配內存的方式:

float **allocateMatrix() { 
    int i; 
    float **m; 

    m = malloc(2*sizeof(float *)); 
    for (i = 0; i < 2; i++) { 
     m[i] = malloc(2*sizeof(float)); 
    } 

    return m; 
} 

int main() { 
    float **m; 

    m = allocateMatrix(); 

    /* do other things 
     fillMatrix(matrix); 
     freeMatrix(&matrix); 
    */ 
}