5

Ai đó có thể khôn ngoan hơn tôi vui lòng giải thích cho tôi tại sao đoạn mã sau bị lỗi? Không có vấn đề phân bổ bộ nhớ bằng cách tham chiếu, nhưng ngay sau khi tôi cố gắng gán bất cứ điều gì hoặc miễn phí bằng cách tham chiếu, segfault xảy ra.Phân bổ mảng động 2D và tham chiếu bằng tham chiếu trong C

Tôi chắc chắn rằng tôi đang thiếu một số khái niệm cơ bản về con trỏ và đi qua tham chiếu, hy vọng một số ánh sáng có thể đượ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

Tôi thực sự hơi ngạc nhiên khi biên dịch. "void allocateMatrix (& m)" có khả năng không nhập m dưới dạng float ** như mong đợi. Ngoài ra, không có tài liệu tham khảo trong C trong cùng một cách mà có trong C + +. – Corbin

+0

tại sao chữ ký cho 'freeMatrix' vv khác nhau khi khai báo và xác định? – keety

+0

keety, Corbin: xin lỗi sao chép dán thất bại, cố định nó – holocron

Trả lời

8

Một tập hợp các vấn đề là ở đây:

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

Bạn cần phải gán cho *m để lấy lại thông tin về mã gọi điện và bạn cũng cần phải phân bổ đến (*m)[i] trong vòng lặp.

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

Có ít nhất một cơ hội mà các chức năng khác là OK. Các fillMatrix() được viết và gọi một cách chính xác, mặc dù nó có thể được đơn giản hóa bằng cách mất ba * từ con trỏ:

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

Nó có thể được khuyến khích để vượt qua ba con trỏ đến freeMatrix() để bạn có thể bằng không con trỏ trong chức năng gọi số:

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

Calling sau đó trở thành:

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

Cảm ơn Jonathan, điều này có ý nghĩa hoàn hảo. – holocron

3

Sử dụng tốt các hướng dẫn. Chỉ cần cố gắng nhất quán với định dạng. Nó cải thiện khả năng đọc và giảm lỗi. ví dụ.

gọi hàm:

allocateMatrix &matrix 
    fillMatrix &matrix 
    freeMatrix &matrix 

tờ khai

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

xử lý

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

Điều này có ý nghĩa, tôi sẽ cố gắng triển khai ngay bây giờ. – holocron

0

trở của con trỏ từ niềm vui của bạn ction có lẽ là cách tốt hơn để cấp phát bộ nhớ:

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); 
    */ 
} 
Các vấn đề liên quan