5

Czy ktoś mądrzejszy niż ja proszę wyjaśnić mi, dlaczego następujące błędy segmentu kodu? Nie ma problemu z przydzieleniem pamięci przez odniesienie, ale gdy tylko spróbuję cokolwiek przypisać lub zwolnić przez odniesienie, nastąpi błąd segfault.2D Dynamiczne przydzielanie macierzy i przekazywanie przez odniesienie w C

Jestem pewien, że brakuje mi jakiegoś podstawowego pojęcia o wskaźnikach i przekazywaniu przez odniesienie, mam nadzieję, że pewne światło może zostać odrzucone.

#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

Jestem trochę zaskoczony, że kompiluje. "void allocateMatrix (& m)" prawdopodobnie nie wpisuje m jako float ** zgodnie z oczekiwaniami. Ponadto nie ma odwołań w C w taki sam sposób, jak w C++. – Corbin

+0

dlaczego podpisy dla 'freeMatrix' itp są różne w deklaracji i definicji? – keety

+0

keety, Corbin: przepraszająca kopia wkleja się niepowodzeniem, poprawiono je – holocron

Odpowiedz

8

jeden zestaw problemów jest tutaj:

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

Należy przypisać do *m, aby uzyskać informacje z powrotem do kodu wywołującego, a także trzeba przydzielić do (*m)[i] w pętli.

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

Istnieje szansa, że ​​inne funkcje są w porządku. fillMatrix() jest napisane i wywoływane prawidłowo, choć może to być uproszczone tracąc trzeci * z palików:

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

to może być wskazane, aby przejść potrójne wskaźnik freeMatrix() tak aby można było wyzerować wskaźnik w funkcja numerem:

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

wywołanie wówczas postać:

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

Dzięki Jonathan, to ma sens. – holocron

3

Dobre wykorzystanie niedokładności. Po prostu spróbuj zachować spójność z formatem. Poprawia czytelność i redukuje liczbę błędów. na przykład

wywołania funkcji:

allocateMatrix &matrix 
    fillMatrix &matrix 
    freeMatrix &matrix 

deklaracje

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

obsługi

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

To ma sens, spróbuję wprowadzić to teraz. – holocron

0

Wracając od wskaźnika z zabawy ction jest prawdopodobnie lepszym sposobem na przydzielenie pamięci:

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); 
    */ 
} 
Powiązane problemy