Malloc all'interno di una chiamata di funzione sembra essere liberato al ritorno?
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.
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;).