5

Qualcuno più saggio di me può spiegarmi perché i seguenti errori del segmento di codice? Non c'è alcun problema ad allocare la memoria per riferimento, ma non appena provo ad assegnare qualcosa o gratuitamente per riferimento, si verifica segfault.Assegnazione di array dinamici 2D e passaggio per riferimento in C

Sono sicuro che mi manca qualche concetto fondamentale di puntatori e passando per riferimento, si spera che si possa far luce.

#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

Sono davvero un po 'sorpreso che compila. "void allocateMatrix (& m)" probabilmente non sta scrivendo m come float ** come previsto. Inoltre, non ci sono riferimenti in C nello stesso modo in cui ci sono in C++. – Corbin

+0

perché le firme per 'freeMatrix' etc sono diverse a dichiarazione e definiton? – keety

+0

keety, Corbin: scusa copia fallita, risolto – holocron

risposta

8

Una serie di problemi è qui:

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

È necessario assegnare a *m per ottenere le informazioni sul codice chiamante e inoltre è necessario assegnare a (*m)[i] nel ciclo.

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

C'è almeno una possibilità che le altre funzioni siano OK. Il fillMatrix() è scritto e invocato correttamente, anche se potrebbe essere semplificata perdendo il terzo * dal puntatore:

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

potrebbe essere consigliabile passare il triplo puntatore freeMatrix() modo che si può azzerare il puntatore nella funzione di chiamata:

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

Calling allora diventa:

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

Grazie Jonathan, questo ha perfettamente senso. – holocron

3

Buon uso di indirezione. Cerca di essere coerente con il formato. Migliora la leggibilità e riduce gli errori. per esempio.

funzione

chiama:

allocateMatrix &matrix 
    fillMatrix &matrix 
    freeMatrix &matrix 

dichiarazioni

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

movimentazione

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

Questo ha senso, cercherò di implementare ora. – holocron

0

Restituzione puntatore dal vostro divertimento Ction è probabilmente il modo migliore per allocare memoria:

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); 
    */ 
} 
Problemi correlati