Malloc dans un appel de fonction semble être libéré au retour?
Question
Je pense que je l'ai compris dans le 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 peut nous éclairer sur les points faibles de ma compréhension, ce serait grandement apprécié.
La solution
Vous passez le pointeur par valeur, et non par référence. Ainsi, quoi que vous fassiez avec arr à l'intérieur de foo ne fera aucune différence en dehors de la fonction foo. Comme m_pGladiator a écrit, une façon est de déclarer une référence à un pointeur comme ceci (uniquement possible en C ++, C ne sait pas à propos des 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 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;
}
Autres conseils
Vous avez alloué arr in foo, mais cette valeur de pointeurs est stockée dans la pile d'appels. Si vous souhaitez le faire, procédez comme suit:
void foo( int ** arr) {
*arr = (int *)malloc( sizeof(int) * 25 );
(*arr)[3] = 69;
}
Et dans le menu principal, passez simplement un pointeur sur foo (comme foo (& amp))
foo reçoit une copie locale du pointeur int, y alloue de la mémoire et la perd quand cette dernière s’étend.
Un moyen 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] de main.
Vous ne pouvez pas changer la valeur de votre argument (arr) s'il n'est pas passé par référence (& amp;). En règle générale, vous souhaitez renvoyer le pointeur. Votre méthode doit donc être:
arr = foo ();
C’est mauvais juju d’essayer de réaffecter des arguments; Je ne recommande pas la solution (& amp;).