Malloc dans un appel de fonction semble être libéré au retour?

Je pense l’avoir au cas le plus fondamental:

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 sortie est la suivante:

 > ./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 quelqu’un pouvait nous éclairer sur les lacunes de ma compréhension, ce serait grandement apprécié.

Vous passez le pointeur par valeur, pas par référence, donc quoi que vous fassiez avec arr inside foo ne fera aucune différence en dehors de la fonction foo. Comme l’a écrit m_pGladiator, une façon est de déclarer une référence à un pointeur comme ceci (uniquement possible en C ++, car C ne connaît pas les références):

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

Une autre façon (mieux, à mon humble avis) est de ne pas passer le pointeur sous forme d’argument mais de renvoyer un pointeur:

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

Et vous pouvez passer un pointeur à un pointeur. C’est la façon de passer en C par référence. Complique un peu la syntaxe mais bien – c’est comme ça que C est …

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

Vous avez alloué arr in foo, mais cette valeur de pointeurs est stockée dans la stack d’appels. Si vous voulez faire cela, faites-le comme ceci:

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

Et en général, il suffit de passer un pointeur sur foo (comme foo (& arr))

foo reçoit une copie locale du pointeur int, lui alloue de la mémoire et la perd lorsque cette dernière est hors de scope.

Une façon de résoudre ce problème pour que foo renvoie le pointeur:

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

Une autre consiste à passer foo un pointeur à un pointeur

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

En C ++, il est plus simple de modifier foo pour accepter une référence à un pointeur. Le seul changement dont vous avez besoin en C ++ est de changer foo en

 void foo(int * & arr) 

Puisque vous passez le pointeur par valeur, le pointeur arr dans main ne pointe pas vers la mémoire allouée. Cela signifie deux choses: vous avez vous-même une fuite de mémoire (NON, la mémoire n’est pas libérée une fois la fonction foo terminée), et lorsque vous accédez au pointeur arr à l’intérieur de main, vous accédez à une plage de mémoire arbitraire. pas 3 et donc free () refuse de travailler. Vous avez de la chance que vous n’ayez pas eu une erreur de segmentation en accédant à arr [3] inside main.

Vous ne pouvez pas changer la valeur de votre argument (arr) s’il n’est pas passé par référence (&). En général, vous voudriez retourner le pointeur, votre méthode devrait donc être:

arr = toto ();

C’est mauvais juju d’essayer de réaffecter des arguments; Je ne recommande pas la solution (&).