Bonjour,
J'aurais besoin de savoir une chose ,
Quel problème ou phénomène peux t'il se produire si on alloue avec un 'new' : un pointer (enregistrement) et qu'on le libère avec la fonction 'free' ? ???
et pour inverse ('malloc' et 'delete') ??
Merci
Version imprimable
Bonjour,
J'aurais besoin de savoir une chose ,
Quel problème ou phénomène peux t'il se produire si on alloue avec un 'new' : un pointer (enregistrement) et qu'on le libère avec la fonction 'free' ? ???
et pour inverse ('malloc' et 'delete') ??
Merci
Bonjour,
L'implosion de l'Univers ...
En fait c'est très simple, c'est un comportement indéfini, donc tu vas avoir des résultats différents selon l'implémentation (donc la bibliothèque, le compilo, le système). Mais dans 99% des cas tu vas simplement corrompre ta mémoire et faire crasher bêtement ton programme.
Ce n'est pas indéfini du tout.
malloc/free gèrent un bloc de mémoire, tandis que new et delete gèrent un pointeur typé.
new et delete sont garanti d'appeler respectivement le constructeur et le destructeur, tandis que malloc et free ne le font pas.
Dans l'absolu, l'appel réellement fait par delete bidule serait bidule->~Bidule(); free(bidule);. Mais un retour à la norme est de rigueur pour les détails.
La conséquence de free(new fstream("fichier"));, c'est que le fichier ne sera pas fermé, parce que son destructeur ne sera pas appelé.
Pour malloc delete, c'est plus pervers, parce que tu détruiras un objet non construit.
ok,
en tout cas pour les classes , il faut passer par new.
Si ça l'est.
Tu ne sais pas si, et où, malloc() et free stockent des informations complémentaires. Chaque compilateur est libre de les implémenter comme il veut. Tu sais peut-être ce que font malloc()/free() et new/delete, en revanche il n'y a aucune information dans les standards par rapport au comportement du programme lorsqu'on fait un mix des deux.
Dans tous les cas en C++ il faut se passer de malloc() et free(). Et si possible ne pas manipuler les pointeurs directement, passer par des classes conçues pour ça (genre les classes de smart pointers). Bien sûr tout dépend après du projet.Citation:
en tout cas pour les classes , il faut passer par new.
Salut,En fait, vous avez tous les deux presque raison, mais plus ou moins tord...
Ce qui provoque un comportement indéterminé, c'est le fait que le constructeur ou que le destructeur ne soit jamais appelé. Par contre, on sait que malloc n'appellera jamais le constructeur et que free n'appellera jamais le destructeur. On peut donc très clairement déterminer ce qui se passe si on fait un mix de new + free ou de malloc + delete: le constructeur ou le destructeur ne sera pas appelé en fonction de ce que l'on a fait.
Après, il se fait que ces deux circonstances auront pour résultat de provoquer un comportement indéfini, mais on est à ce niveau déjà "une étape plus loin" ;)
Merci Koala01 :D
Vu de la norme, l'appel de delete sur un pointeur non obtenu par new est en lui-même un comportement indéfini, indépendamment des constructions/destructions :
Il n'est donc pas même pas certain que dans un tel cas il y ait une tentative d'appel du destructeur, même si c'est un comportement possible voire probable.Citation:
Otherwise, the behavior is undefined if the value supplied to operator delete(void*) in the standard library is not one of the values returned by a previous invocation of either operator new(std::size_t) or operator new(std::size_t, const std::nothrow_t&) in the standard library, and the behavior is undefined if the value supplied to operator delete[](void*) in the standard library is not one of the values returned by a previous invocation of either operator new[](std::size_t) or operator new[](std::size_t, const std::nothrow_t&) in the standard library.
Une implémentation peut (et à titre personnel, j'apprécierais) fournir un mode debug où ces appels claquent dans une assertion fausse.
Ca, je n'en suis pas sûr, parce qu'il me semble que les segments mémoires sont décrits par la norme, et que les quatre fonctions s'occupent du même segment (heap)
Oui mais c'est pas parce qu'elles gèrent toutes le tas qu'elles sont "compatibles", ou du moins qu'on puisse résumer un new suivi d'un free() par "un objet alloué puis construit puis seulement libéré".
Imagine (c'est un exemple) que new alloue X octets de plus d'en-tête pour stocker des métadonnées, octets utilisés ensuite par delete pour une raison ou une autre, et que malloc() crée lui aussi un en-tête mais avec des données qui n'ont rien à voir. Si tu new puis tu free(), cette dernière risque de planter à cause des métadonnées qui sont pas formatées comme elles le devraient (càd par malloc() et non new).
Mais ça, on ne peut pas le savoir, parce que les compilos et bibliothèques décident de leur implémentation, et les standards (C et C++) ne disent rien à ce propos.
Donc c'est un comportement indéfini.
A mes yeux, dire que free() est l'équivalent d'un delete sans appel du destructeur, est faux.
Mais pourquoi tu veux faire ça ? :weird:
Et pourtant, regarde comment s'utilise et s'implémente un placement new, tu verras que c'est a peu près ca.
Pour être précis, je dis qu'un new est un malloc suivi d'un placement new.
Comme je n'ai pas souvenir du placement delete, c'est une autre histoire.
Oui mais le problème est que newalloue sur le "stock libre" (une zone mémoire) et que mallocalloue sur le "Tas" (une autre zone mémoire, c'est comme si on prenait deux livres semblables, et que l'un on le met sur l'étage du haut et que l'autre sur l'étage du bas d'une étagère, maintenant il se peut que les deux zones se trouvent dans le même endroit, cela dépend de l'implémentation, ce qui donnerait certainement des résultats catastrophiques.
En plus de ça certaines fonctions ne sont pas accessible quand on alloue avec malloc(), c'est qu'il faut connaitre dès le départ la taille de l'objet, et que certaines fonctions ne sont pas accessibles tel que le constructeur et le destructeur, sans oublier le faire que malloc retourne un type void *.
Maintenant si tu veux déclencher une troisième guerre mondiale.:oops:
Conceptuellement, ce n'est pas totalement faux. Mais ce n'est pas vrai non plus :)
Tu peux dire plus précisément qu'un new, c'est une allocation de mémoire brute, suivi d'un placement new. Et qu'un delete correspond à l'appel explicite du destructeur suivi d'une désallocation de mémoire à l'aide d'une fonction compatible avec celle utilisée pour l'allocation.
Si à la main tu fais malloc + placement new, tu devras faire destructeur explicite + free.
Mais si tu fais new, tu n'auras pas le droit de faire destructeur explicite + free, tu devras faire delete.
12.4/13 : appel explicite du destructeur.
Et ça devient encore plus compliqué quand on rajouter new[]/delete[] dans l'équation, car new[] doit forcément stocker quelque part le nombre d'objets alloués.