2010-03-25 14 views
11

¿La memoria asignada con malloc no persiste fuera del alcance de la función?

Hola,

que soy un poco nuevo en función malloc de C, pero por lo que sé que debe almacenar el valor en el montón, por lo que puede hacer referencia a él con un puntero desde fuera del alcance original . Creé un programa de prueba que se supone que debe hacer esto, pero sigo obteniendo el valor 0 después de ejecutar el programa. ¿Qué estoy haciendo mal?

int f1(int * b) { 
b = malloc(sizeof(int)); 
*b = 5; 
} 

int main() { 
int * a; 
f1(a); 
printf("%d\n", a); 
return 0; 
} 

Respuesta

6

La memoria misma persiste, pero las fugas, ya que no está proporcionando el puntero asignado a la persona que llama. Además, está imprimiendo a cuando debería imprimir *a. Finalmente, no está devolviendo un int desde f1.

Probar:

void f1(int **b) { 
*b = malloc(sizeof(int)); 
**b = 5; 
} 

int main() { 
int *a; 
f1(&a); 
printf("%d\n", *a); 
free(a); 
return 0; 
} 
0

Su problema es en realidad no está relacionado con malloc, sino más bien el hecho de que estás pasando el valor del puntero tiene actualmente, en lugar de la dirección de la misma. Pruebe lo siguiente:

int f1(int ** b) { 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 

int main() { 
    int * a; 
    f1(&a); 
    printf("%d\n", *a); 
    return 0; 
} 

Al pasar el valor del puntero como eras, no había manera para el valor malloc creado para ser almacenada en el puntero.

+3

Esto es de nuevo pasar por valor. Está pasando la dirección de a por valor. ** No hay pase por referencia en C ** – raj

+0

Lo suficientemente bueno. Actualizado para ser más preciso en C. – Dusty

0

La dirección int *b se borra cuando la función regresa. Para guardarlo, es necesario utilizar un puntero de un puntero

int f1(int ** b) { 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 
8

Parece que estás malentendido una parte fundamental de cómo funciona C - es decir, que se trata de un lenguaje 'pass-by-value' . Para que main() sepa sobre la memoria que ha asignado, debe recuperarla. El siguiente código le hará lo que quiera:

int f1(int **b) 
{ 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 

int main(int argc, char **argv) 
{ 
    int *a; 
    f1(&a); 
    printf("%d\n", *a); 
    return 0; 
} 

Existen un par de diferencias entre este código y el suyo; primero, la firma de f1() ha cambiado, de modo que puede devolver el resultado de la llamada malloc() en el puntero pasado. A continuación, la llamada a f1() se ha cambiado para pasar la dirección de a en lugar de a en sí misma; es importante si desea que se 'complete' por f1(), por así decirlo. Finalmente, se ha cambiado el printf() en main() para imprimir el valor apuntado en lugar del puntero.

+7

No entiendo por qué todos han pasado directamente a utilizar un puntero a puntero: esa no es la mejor manera de explicar cómo hacerle esto a alguien que está teniendo problemas con un parte fundamental del lenguaje. ¿Por qué no simplemente devuelve el puntero desde 'f1()'? – caf

+0

@caf, sí! ¡eso es simple para que un principiante lo entienda! – raj

+0

¡Muchas gracias por los comentarios de todos! Mi código funciona ahora No puedo hacer que la función devuelva el puntero, porque la función en mi proyecto real ya está devolviendo algo más ... ¡Gracias de nuevo! –

22

Sí! a se pasan por valorb manera que el puntero en la función f1 será local .. o bien volver b,

int *f1() { 
    int * b = malloc(sizeof(int)); 
    *b = 5; 
    return b; 
} 

int main() { 
    int * a; 
    a = f1(); 
    printf("%d\n", *a); 
    // keep it clean : 
    free(a); 
    return 0; 
} 

o pasar dirección a 's

int f1(int ** b) { 
    *b = malloc(sizeof(int)); 
    **b = 5; 
} 

int main() { 
    int * a; 
    f1(&a); 
    printf("%d\n", *a); 
    // keep it clean : 
    free(a); 
    return 0; 
} 
5

vamos a suponer que se asigna un valor de NULL antes de llamar a la función f1.Ahora, como se define f1, toma su argumento (puntero a int) por valor. Es b será otra variable del tipo int * que será copia de a. Entonces b también tendrá un valor de NULL. Ahora, en f1, cambie el valor por b asignándole la dirección de memoria asignada dinámicamente usando malloc. Digamos que la dirección de memoria es 0x123. Como resultado de esta asignación, b ha cambiado su valor NULL-0x123 pero a (en main) continúa para mantener NULL, porque el cambio b no cambiará a, ya que son dos variables separadas. Como resultado de esto, cuando regrese de la función f1 a no se modificará.

Hay 2 formas de solucionar esto. Uno puede hacer que la función f1 devuelva el valor del b cambiado y luego asignarlo a a en main y dos, puede pasar la dirección a para que cualquier cambio realizado en f1 afectará también a main.

// f1 now returns the value of b. 
int* f1() { 
int *b = malloc(sizeof(int)); 
*b = 5; 
return b; 
} 

int main() { 
int *a = NULL; 
a = f1(); // assign the return value of f1 to a. 
printf("%d\n", *a); // prints 5...not its *a not just a. 
return 0; 
} 

.

// f1 now takes the address of a. 
void f1(int **b) { 
*b = malloc(sizeof(int)); // you are actually altering a indirectly. 
**b = 5; 
} 

int main() { 
int *a = NULL; 
f1(&a); // now pass the address of a to f1. 
printf("%d\n", *a); // prints 5...not its *a not just a. 
return 0; 
} 
Cuestiones relacionadas