Pregunta

Creo que lo he reducido al caso más básico:

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 esta:

> ./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 falla mi comprensión, se lo agradecería mucho.

¿Fue útil?

Solución

Pasas el puntero por valor, no por referencia, por lo que cualquier cosa que hagas con arr dentro de foo no hará ninguna diferencia fuera de la función foo.Como escribió m_pGladiator, una forma es declarar una referencia a un puntero como este (solo 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;
}

Otra forma (mejor en mi humilde opinión) es no pasar el puntero como argumento sino 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 puedes pasar un puntero a un puntero.Esa es la forma C de pasar por referencia.Complica un poco la sintaxis, pero bueno, así es C...

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;
}

Otros consejos

Ha asignado arr en foo, pero el valor de ese puntero se almacena en la pila de llamadas.Si quieres hacer esto, hazlo así:

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

Y en main, simplemente pasa un puntero a foo (como foo(&arr))

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

Una forma de solucionar este problema es hacer que foo devuelva el puntero:

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

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

Otra es pasar foo un puntero a un puntero.

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

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

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

void foo(int * & arr)

Dado que está pasando el puntero por valor, el puntero arr dentro de main no apunta a la memoria asignada.Esto significa dos cosas:tienes una pérdida de memoria (NO, la memoria no se libera después de que se completa la función foo), y cuando accedes al puntero arr dentro de main estás accediendo a un rango arbitrario de memoria, por lo tanto, no obtienes 3 impresos out y, por lo tanto, free() se niega a funcionar.Tienes suerte de no haber tenido un error de segmentación al acceder a arr[3] dentro de main.

No puede cambiar el valor de su argumento (arr) si no se pasa por referencia (&).En general, querrás devolver el puntero, por lo que tu método debería ser:

arr=foo();

Es un mal juju intentar reasignar argumentos;No recomiendo la solución (&).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top