5

¿Alguien más inteligente que yo puede explicarme por qué faltan las siguientes fallas en el segmento del código? No hay problema para asignar la memoria por referencia, pero tan pronto como trato de asignar algo o de forma gratuita por referencia, ocurre segfault.Asignación de matriz dinámica bidimensional y transferencia por referencia en C

Estoy seguro de que me falta un concepto fundamental sobre los punteros y el paso por referencia, ojalá se pueda arrojar algo de luz.

#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

Estoy realmente un poco sorprendido de que compile. "void allocateMatrix (& m)" probablemente no esté escribiendo m como float ** como se esperaba. Además, no hay referencias en C de la misma manera que existen en C++. – Corbin

+0

¿por qué las firmas para 'freeMatrix' etc. son diferentes en la declaración y la definición? – keety

+0

keety, Corbin: lo siento copiar pegar no, lo solucionó – holocron

Respuesta

8

Un conjunto de problemas está aquí:

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

Debe asignar al *m para obtener la información de nuevo al código de llamada, y también tendrá que asignar al (*m)[i] en el ciclo.

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

Hay al menos una posibilidad de que las otras funciones sean correctas. El fillMatrix() se escribe y se invoca correctamente, a pesar de que podría simplificarse por la pérdida de la tercera * del puntero:

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

podría ser aconsejable para pasar el triple puntero a freeMatrix() de modo que usted puede poner a cero el puntero en el función que llama:

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

llamando entonces es:

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

Gracias Jonathan, esto tiene mucho sentido. – holocron

3

Buen uso de la indirección. Solo trata de ser consistente con el formato. Mejora la legibilidad y reduce los errores. p.ej.

función

llama:

allocateMatrix &matrix 
    fillMatrix &matrix 
    freeMatrix &matrix 

declaraciones

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

manejo

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

Esto tiene sentido, intentaré implementar ahora. – holocron

0

Volviendo de puntero desde su diversión ction es probablemente la mejor forma de asignar 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); 
    */ 
} 
Cuestiones relacionadas