[C]Allocation memoire dans fonction externe

Hello,

une petite question encore, voici la situation :
Dans mon main.c je déclare un pointeur vers des int :

j’ai ensuite trois fonction :

void allocation_memoire(int* vecteur_test, int taille); void initialisation(int* vecteur_test, int taille); void liberation_memoire(int* vecteur_test);

voici le corps de ces fonctions :

[code]void allocation_memoire(int* vecteur_test, int taille){
vecteur_test = (int*) malloc(TAILLEsizeof(int));
if(vecteur_test == (int
) NULL){
printf(“erreur\n”);
exit(EXIT_FAILURE);
}
printf(“fin allocation\n”);
}
void initialisation(int* vecteur_test, int taille){
int i;

for(i=0; i<taille; i++){
	vecteur_test[i] = -1;
}
printf("fin initialisation\n");

}

void liberation_memoire(int* vecteur_test){
free((void*)vecteur_test);
vecteur_test = (int*) NULL;
printf(“fin liberation\n”);
}[/code]

Dans mon programme principal, je fais simplement un appel à ces trois fonctions l’une après l’autre. Arrivé à l’initialisation, le programme sort un segFault. Mais je ne comprends pas pourquoi ? L’allocation mémoire se fait en local lorsque cela est fait dans une fonction, et au retour de fonction, l’adresse de l’espace mémoire alloué n’est plus valide, quelque chose dans le style ?

Merci d’avance,
Patrick

Il faut que tu retournes ton int * dans ta fonction allocation_memoire, si une fonction modifie ses arguments cela ne change rien en dehors de la fonction.

D’accord pour un int, mais là je passe un pointeur… il le passe par copie à la fonction ?!?

Un pointeur est une valeur entière comme une autre, et il est passé à la fonction comme toute autre valeur, c’est-à-dire en faisant une copie de la valeur dans un registre ou sur la pile (je sais plus exactement comment c’est sur les différentes architectures).

On dit qu’on passe des arguments par valeur ou par référence, mais ici c’est la première case de ton tableau qui est passée par référence, donc c’est *vecteur_test que tu peux modifier dans la fonction, pas vecteur_test qui est passée par valeur lui :smiley:

C’est bien quand même de connaître un peu comment ça marche en bas niveau pour comprendre pourquoi le compilateur et le langage fait comme ça et pas autrement B)

[quote=« kineox, post:4, topic: 30244 »]Un pointeur est une valeur entière comme une autre, et il est passé à la fonction comme toute autre valeur, c’est-à-dire en faisant une copie de la valeur dans un registre ou sur la pile (je sais plus exactement comment c’est sur les différentes architectures).

On dit qu’on passe des arguments par valeur ou par référence, mais ici c’est la première case de ton tableau qui est passée par référence, donc c’est *vecteur_test que tu peux modifier dans la fonction, pas vecteur_test qui est passée par valeur lui :smiley:

C’est bien quand même de connaître un peu comment ça marche en bas niveau pour comprendre pourquoi le compilateur et le langage fait comme ça et pas autrement B)[/quote]
Ok merci, et donc pour la liberation de mémoire, le free fonctionnera, mais pas l’assignation à NULL ?

[quote=“Maverick, post:1, topic: 30244”]Dans mon programme principal, je fais simplement un appel à ces trois fonctions l’une après l’autre. Arrivé à l’initialisation, le programme sort un segFault. Mais je ne comprends pas pourquoi ? L’allocation mémoire se fait en local lorsque cela est fait dans une fonction, et au retour de fonction, l’adresse de l’espace mémoire alloué n’est plus valide, quelque chose dans le style ?
Merci d’avance,
Patrick[/quote]
Bon tu m’excusera mais il est 23h40, si je suis pas clair, dis le et je te refait tout demain matin B)

Il faut se souvenir de tes cours de C:
Quand tu fais:

void toto(int i)
Tu passe i par valeur, et quand tu sors, i a pour valeur celle d’avant l’execution de la fonction, meme si dans celle ci, tu as modifier i.

void toto(int *i)
Tu passe i par pointeur, donc tu peux modifier la valeur POINTEE par i, mais tu ne peux pas modifier le pointeur en lui meme puisque celui ci est passe par valeur.

void toto (int **i)
Tu passe i par pointeur de pointeur, donc tu peux non seulement modifier la valeur sur laquelle pointe le pointeur, mais AUSSI le pointeur en lui meme (attention aux initialisation)

Donc vu ta fonction, tu veux modifier le pointeur de i, et la, c’est pas jouable.
donc tu as deux choix:
_void toto(int **i)
_int *toto()

C’est clair?

LoneWolf
Trop facile les pointeurs.

Exact. Du moins ce sera assigné seulement localement à la fonction.

oui oui, merci tout le monde. J’avais bien compris la réponse de Kineox.

ps. je n’ai jamais eu de cours de C B).

Juste un petit conseil, si tu veux clarifier ton code transforme tes fonctions en macro.

par exemple pour l’allocation mémoire ça donne quelque chose du genre

#define MEMALLOC(_o,_t,_n) do { \ if (!(_o=(_t *)malloc (sizeof (_t)*(_n)))) \ fprintf (stderr, "ERREUR allocation memoire" \ " impossible de %s de type %s[%1d], dans %s"\ " ligne %1d\n", #_o, #_t, (_n), \ __FILE__, __LINE__), abort (); } while (0)

En plus de ne pas te retrouver avec des chose du genre

int *ptr = NULL; ptr = allocation_memoire(ptr, 10);
Tu gagne aussi l’avantage d’avoir une macro marchant pour tous types de données (même les types complexes comme les structures), ce qui facilite la réutilisation et permet une cohérence dans le code (tu n’a pas une fonction pour les int, une pour les float…).

Par contre garre aux effets de bord, je ne sais pas s’il y a un risque avec cette macro, mais on n’est jamais trop prudent.

tu la trouve vraiment plus propre ta macro ?

alors oui c est surement plus rapide a executer, et ca te sort directement l endroit ou ca a merdé … mais etre le fait de mettre du code dans un .h, et le do while(0) tout crado, nan clairement pas.

en plus, un coup de gdb, un breakpoint, et un coup d oeil sur la stack … ca marche aussi bien

Le do while(0) est justement une des choses qui rend cette macro “propre”. Pour plus d’explications sur le sujet : http://c-faq.com/cpp/multistmt.html

Ce qui rend ta maccro hideuse, c’est surtout le manque d’indentation et le nommage de tes variables (je songe à monter une association de lutte contre les varaibles de moins de 3 caractères de long ^^)

Plus le scope est large, plus le nom doit être explicite. Là le scope il fait 3 lignes, y’a pas besoin de noms à rallonge, ça rendrait le truc moins lisible.
Et puis aussi Kzi, l’idée là c’est de fournir un message quand ça plante en dehors du debugger.