5

Kann jemand klüger als ich bitte erklären, warum die folgenden Code-Segment Fehler? Es gibt kein Problem, den Speicher durch Verweis zuzuweisen, aber sobald ich versuche, irgendetwas oder durch Verweis zuzuweisen, tritt segfault auf.2D Dynamische Array-Zuweisung und Weitergabe nach Referenz in C

Ich bin mir sicher, dass ich ein grundlegendes Konzept über Zeiger und Weitergabe durch Verweis vermisse, hoffentlich kann etwas Licht vergossen werden.

#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

Ich bin eigentlich ein bisschen überrascht, dass kompiliert. "void allocateMatrix (& m)" tippt m wahrscheinlich nicht als Float ** wie erwartet ein. Außerdem gibt es in C keine Referenzen in der gleichen Weise wie in C++. – Corbin

+0

Warum sind Signaturen für 'freeMatrix' usw. bei Deklaration und Definition unterschiedlich? – keety

+0

keety, Corbin: sorry Kopieren einfügen fehlgeschlagen, behoben – holocron

Antwort

8

Eine Reihe von Problemen ist hier Handhabung:

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

Sie müssen *m zuweisen, um die Informationen zurück an den aufrufenden Code zu erhalten, und Sie müssen auch (*m)[i] in der Schleife zuordnen.

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

Es gibt zumindest eine Chance, dass die anderen Funktionen in Ordnung sind. Die fillMatrix() geschrieben und aufgerufen richtig, obwohl es durch den Verlust der dritten * vom Zeiger vereinfacht werden könnte:

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

Es könnte ratsam sein, den Triple-Zeiger auf freeMatrix() so passiert, dass Sie den Mauszeiger in der Null können Aufruf Funktion:

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

Aufruf wird dann:

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

Danke Jonathan, das macht Sinn. – holocron

3

Gute Verwendung von Indirection. Versuchen Sie einfach, mit dem Format übereinzustimmen. Es verbessert die Lesbarkeit und reduziert Fehler. z.B.

Funktion aufruft:

allocateMatrix &matrix 
    fillMatrix &matrix 
    freeMatrix &matrix 

Erklärungen

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

Das macht Sinn, ich werde versuchen, jetzt zu implementieren. – holocron

0

des Zeigers der Rückkehr von Ihrem Spaß ction ist wahrscheinlich der bessere Weg, um Speicher zu reservieren:

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