5

Может ли кто-нибудь мудрее, чем мне, объяснять мне, почему следующие ошибки сегмента кода? Нет проблем с распределением памяти по ссылке, но как только я попытаюсь присвоить что-либо или освободить по ссылке, произойдет segfault.Выделение и передача 2D динамических массивов по ссылке в 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

+0

Почему подписи для 'freeMatrix' и т. Д. Разные при объявлении и определении? – keety

+0

keety, Corbin: извините, скопируйте пасту, не удалось, исправлено – holocron

ответ

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

Спасибо Джонатан, это имеет смысл. – holocron

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

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); 
    */ 
} 
Смежные вопросы