Malloc all'interno di una chiamata di funzione sembra essere liberato al ritorno?

StackOverflow https://stackoverflow.com/questions/105477

  •  01-07-2019
  •  | 
  •  

Domanda

Penso di averlo capito nel caso più elementare:

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

L'output è questo:

> ./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
>

Se qualcuno potesse far luce su dove la mia comprensione sta fallendo, sarebbe molto apprezzato.

È stato utile?

Soluzione

Passi il puntatore per valore, non per riferimento, quindi qualunque cosa tu faccia con arr inside foo non farà differenza al di fuori della funzione foo. Come m_pGladiator ha scritto un modo è dichiarare un riferimento a un puntatore come questo (possibile solo in C ++ tra Cw. C non conosce i riferimenti):

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

Un altro modo (migliore per me) è non passare il puntatore come argomento ma restituire un puntatore:

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

E puoi passare un puntatore a un puntatore. Questo è il modo C per passare per riferimento. Complica un po 'la sintassi ma bene - ecco come è 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;
}

Altri suggerimenti

Hai assegnato arr in foo, ma il valore di questi puntatori è memorizzato nello stack di chiamate. Se vuoi farlo, fallo in questo modo:

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

E in generale, passa semplicemente un puntatore a foo (come foo (& amp; arr))

foo riceve una copia locale del puntatore int, alloca memoria ad essa e perde quella memoria quando esce dal campo di applicazione.

Un modo per risolvere il problema per ottenere foo per restituire il puntatore:

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

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

Un altro è passare un puntatore a un puntatore

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

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

In C ++ è più semplice modificare foo per accettare un riferimento a un puntatore. L'unica modifica di cui hai bisogno in C ++ è cambiare foo in

void foo(int * & arr)

Dato che stai passando il puntatore per valore, il puntatore arr all'interno di main non punta alla memoria allocata. Ciò significa due cose: hai una perdita di memoria (NO, la memoria non viene liberata dopo il completamento della funzione foo), e quando accedi al puntatore arr all'interno di main stai accedendo a un intervallo arbitrario di memoria, quindi non vengono stampati 3 e quindi free () si rifiuta di funzionare. Sei fortunato a non aver riscontrato un errore di segmentazione quando accedi ad arr [3] in main.

Non puoi cambiare il valore del tuo argomento (arr) se non viene passato per riferimento (& amp;). In generale, si desidera restituire il puntatore, quindi il metodo dovrebbe essere:

arr = foo ();

È brutto juju provare a riassegnare argomenti; Non consiglio la soluzione (& amp;).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top