2008-09-19 7 views
17

creo que lo tengo hasta el caso más básico:Malloc dentro de una llamada a función parece liberarse a la vuelta?

int main(int argc, char ** argv) { 
    int * arr; 

    foo(arr); 
    printf("car[3]=%d\n",arr[3]); 
    free (arr); 
    return 1; 
} 

void foo(int * arr) { 
    arr = (int*) malloc(sizeof(int)*25); 
    arr[3] = 69; 
} 

La salida es la siguiente:

> ./a.out 
car[3]=-1869558540 
a.out(4100) malloc: *** error for object 0x8fe01037: Non-aligned pointer 
         being freed 
*** set a breakpoint in malloc_error_break to debug 
> 

Si alguien puede arrojar luz sobre dónde está fallando mi entender, sería ser muy apreciado.

Respuesta

47

pasar el puntero por valor, no por referencia, así que cualquier cosa que hagas con arr dentro de foo no hará la diferencia fuera de la función foo. Como m_pGladiator escribió una forma es declarar una referencia a puntero como esto (sólo es posible en C++ por cierto C no sabe acerca de las referencias.):

int main(int argc, char ** argv) { 
    int * arr; 

    foo(arr); 
    printf("car[3]=%d\n",arr[3]); 
    free (arr); 
    return 1; 
} 

void foo(int * &arr) { 
    arr = (int*) malloc(sizeof(int)*25); 
    arr[3] = 69; 
} 

Otro (mejor en mi humilde opinión) forma es no pasar el puntero como un argumento pero para devolver un puntero:

int main(int argc, char ** argv) { 
    int * arr; 

    arr = foo(); 
    printf("car[3]=%d\n",arr[3]); 
    free (arr); 
    return 1; 
} 

int * foo(void) { 
    int * arr; 
    arr = (int*) malloc(sizeof(int)*25); 
    arr[3] = 69; 
    return arr; 
} 

Y puede pasar un puntero a un puntero. Esa es la forma C de pasar por referencia. Complica la sintaxis un poco, pero bien - así es como C es ...

int main(int argc, char ** argv) { 
    int * arr; 

    foo(&arr); 
    printf("car[3]=%d\n",arr[3]); 
    free (arr); 
    return 1; 
} 

void foo(int ** arr) { 
    (*arr) = (int*) malloc(sizeof(int)*25); 
    (*arr)[3] = 69; 
} 
+0

¿Puedo decir, por favor, no arrojar el valor de retorno de malloc? No es obligatorio y puede ocultar errores. – freespace

+0

@freespace, es un hábito que he desarrollado a lo largo de los años. Todos y luego tengo que enviar mi código a través de herramientas de análisis de código estático, y se quejan de que no lanzan punteros. –

+0

Perdón por dejarlo colgando sin respuesta: no hay una buena manera de encontrar respuestas en los comentarios a menos que sondeara todos mis comentarios :) He dejado la respuesta en http://stackoverflow.com/questions/108768/needless- puntero-moldes-en-C# 108781 – freespace

6

Has asignado el acceso a foo, pero ese valor de los punteros se almacena en la pila de llamadas. Si quieres hacer esto, hacerlo de esta manera:

void foo(int ** arr) { 
    *arr = (int *)malloc(sizeof(int) * 25); 
    (*arr)[3] = 69; 
} 

Y en principal, basta con pasar un puntero a foo (como foo (& arr))

0

No se puede cambiar el valor de su argumento (arr) si no se pasa por referencia en (&). En general, le gustaría devolver el puntero, por lo que su método debe ser:

arr = foo();

Es una mala jugada intentar reasignar argumentos; No recomiendo la solución (&).

3

foo recibe una copia local del puntero int, le asigna memoria y pierde esa memoria cuando se sale del alcance.

Una forma de solucionar este problema para conseguir foo para devolver el puntero:

int * foo() { 
    return (int*) malloc(sizeof(int)*25); 
} 

int main() { 
    int* arr = foo(); 
} 

Otra es la de pasar foo un puntero a un puntero

void foo(int ** arr) { 
    *arr = malloc(...); 
} 

int main() { 
    foo(&arr); 
} 

En C++ es más sencillo de modificar foo aceptar una referencia a un puntero. El único cambio que necesita en C++ es cambiar foo a

void foo(int * & arr) 
1

Debido a que su están pasando el puntero por valor, el puntero dentro arr principal no está apuntando a la memoria asignada. Esto significa dos cosas: tienes una fuga de memoria (NO, la memoria no se libera después de completar la función foo), y cuando accedes al puntero arr en main estás accediendo a un rango arbitrario de memoria, por No se imprimen 3 y, por lo tanto, free() se niega a trabajar. Tienes suerte de que no hayas tenido un error de segmentación al acceder a arr [3] dentro de main.

Cuestiones relacionadas