Quand faut il utiliser new ?

Quand faut il utiliser new ? - C++ - Programmation

Marsh Posté le 13-04-2012 à 19:41:19    

Bonjour,
j'ai une question toute bête, mais je n'arrive pas à trouver la réponse dans les divers cours de c++ en ligne...
 
Dans quels cas faut-il utiliser new ?
 
Par exemple, si une fonction déclare un tableau et le renvoie comme résultat, faut-il utiliser new pour alouer ce tableau ?
 
Merci  !

Reply

Marsh Posté le 13-04-2012 à 19:41:19   

Reply

Marsh Posté le 13-04-2012 à 20:02:58    

Tu utilises new quand tu fais de l'allocation mémoire sur le tas et non sur la pile.
Tu as 2 manières de déclarer une variable, un tableau ou autre objet primitif: sur le tas, ou sur la pile. Sur la pile, l'objet ne sera plus accessible dès que tu sortiras du scope {...} dans lequel il a été déclaré. Pour ça, il faut déclarer sur le tas. D'autre part, la taille de la pile est limitée, il faut éviter d'y coller bcp de gros objets sous peine de "stack overflow". C'est donc une zone mémoire pour les objets temporaires.

 

Les objets sur le tas, eux, ont une durée de vie qui s'arrête à l'appel d'un delete ou à la terminaison du programme.
Les free et les delete doivent être rigoureusement appairés sous peine de plantage ou de fuite mémoire. Pour éviter cela, une habitude à prendre dès le début est d'écrire le delete juste après avoir écrit le new, de façon à avoir en tête la durée de vie de l'objet alloué.


Message édité par el muchacho le 13-04-2012 à 20:07:34

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 13-04-2012 à 20:03:45    

Ben oui, enfin tout dépend.
 
Le problème, c'est que si tu écris ça :
 

Code :
  1. int * foo()
  2. {
  3. int *a = new int [rand()%80];
  4. return a;
  5. }


 
Cette fonction créé un nouveau tableau, qui aura un nombre de cases prit au hasard entre 0 et 79, le soucis c'est qu'une fois ton pointeur retourné, tu n'as aucun moyens d'avoir son nombre de case, sauf si tu le sais d'avance.
Si tu as besoin d'une fonction qui créé un tableau dont tu ne sais pas forcément la taille, j'te conseille plutôt de passer par les std::vector, ou alors une structure du style  :

Code :
  1. struct tableau_int
  2. {
  3.   int * valeurs;
  4.   int taille;
  5. };


 
New permet simplement de créer des nouvelles variables dans la mémoire dynamiquement, et renvoit l'adresse où est cette nouvelle variable.
Bon, le soucis, c'est que le C++ est dépourvu de Garbage Collector, ce qui veut dire qu'il faut que tu utilises delete pour supprimer cette nouvelle variable, auquel cas la variable est perdue dans la mémoire.
 
Petit exemple pour le delete :
 

Code :
  1. int * A = new int; // On créé une nouvelle variable, A récupérera son adresse  
  2. delete A; // On supprime la variable à l'adresse donnée par A
  3. int * B = new int [17]; // On créé 17 variables, les adresses de celles-ci sont contigu (ce qui permet les [] ), c-a-d l'une après l'autre, B récupère l'adresse de la première
  4. delete [] B; // Etant donné que B est un "tableau", faut préciser lors du delete via []


 


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 13-04-2012 à 20:10:39    

Ok, merci beaucoup à vous deux, vos deux réponses sont bien précises et complémentaires ! :)
 :jap:  :jap:


Message édité par islington le 13-04-2012 à 20:11:31
Reply

Marsh Posté le 14-04-2012 à 18:39:51    

Terminapor a écrit :

New permet simplement de créer des nouvelles variables dans la mémoire dynamiquement, et renvoit l'adresse où est cette nouvelle variable.
Bon, le soucis, c'est que le C++ est dépourvu de Garbage Collector, ce qui veut dire qu'il faut que tu utilises delete pour supprimer cette nouvelle variable, auquel cas la variable est perdue dans la mémoire.


 
C'est marrant, je trouve que c'est un avantage :o
 
Pour en revenir au sujet :
Accessoirement, si tu fais du C++ avec la toute dernière norme, tu ne dois presque jamais utiliser de new. Tu dois à la place passer par des classes qui vont clairement indiquer pour toi la durée de vie de ton objet (unique_ptr, shared_ptr ...).


---------------
last.fm
Reply

Marsh Posté le 14-04-2012 à 21:11:31    

Tu peux donner un exemple ? J'ai besoin d'un petit raffraichissement... :)


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 14-04-2012 à 22:51:51    

Mr Sutter explique bien tout ça à 9 min 15 dans la vidéo http://channel9.msdn.com/Events/La [...] rmat=html5
(très bonne vidéo dans l'ensemble d'ailleurs)


Message édité par SquiZZ le 14-04-2012 à 22:53:53
Reply

Marsh Posté le 14-04-2012 à 23:42:03    

theshockwave a écrit :


 
C'est marrant, je trouve que c'est un avantage :o
 
Pour en revenir au sujet :
Accessoirement, si tu fais du C++ avec la toute dernière norme, tu ne dois presque jamais utiliser de new. Tu dois à la place passer par des classes qui vont clairement indiquer pour toi la durée de vie de ton objet (unique_ptr, shared_ptr ...).


Ben oui et non, le soucis c'est que quand on commence, ben on oublie des deletes par-ci par là :D
 
Ceci dit, j'ai une question, si on fait plein d'allocs mémoire pas supprimées, l'OS s'en chargera à la fermeture du programme ?


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 15-04-2012 à 01:28:30    

Terminapor a écrit :


Ben oui et non, le soucis c'est que quand on commence, ben on oublie des deletes par-ci par là :D
 
Ceci dit, j'ai une question, si on fait plein d'allocs mémoire pas supprimées, l'OS s'en chargera à la fermeture du programme ?


 
Oui Encore heureux.

Reply

Marsh Posté le 15-04-2012 à 11:24:44    

Terminapor a écrit :


Ben oui et non, le soucis c'est que quand on commence, ben on oublie des deletes par-ci par là :D
 
Ceci dit, j'ai une question, si on fait plein d'allocs mémoire pas supprimées, l'OS s'en chargera à la fermeture du programme ?

De nos jours, oui.
Autrefois (le bon temps de Windows 3.1 par exemple) non.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 15-04-2012 à 11:24:44   

Reply

Marsh Posté le 15-04-2012 à 14:51:47    

Roh, chouette alors, on m'avait dit que justement Windows récupérait super mal la mémoire lorsqu'un log était fermé, mais ça a pas l'air d'actualité :D
 
Merki :jap:


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 15-04-2012 à 17:39:27    

Terminapor a écrit :

Roh, chouette alors, on m'avait dit que justement Windows récupérait super mal la mémoire lorsqu'un log était fermé, mais ça a pas l'air d'actualité :D
 
Merki :jap:


 
Si tu veux approfondir, tu pourras te trouver un peu de lecture sur la MMU que tu trouveras dans tout CPU "moderne" et sur l'adressage virtuel des processus (qui fait que tu ne risques pas d'aller malencontreusement perturber le programme d'à côté)


---------------
last.fm
Reply

Marsh Posté le 15-04-2012 à 18:04:56    

Dans ce cas, comment les types font pour faire des logiciels qui permettent de modifier la mémoire d'un programme ? Techniquement, l'os n'est pas supposé empêcher ça ?


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 15-04-2012 à 22:09:16    

Terminapor a écrit :

Dans ce cas, comment les types font pour faire des logiciels qui permettent de modifier la mémoire d'un programme ? Techniquement, l'os n'est pas supposé empêcher ça ?


Je suppose que tu parles des attaques par shellcode ?
Tu modifies le flot d'instructions du programme lui-même. En gros, quand ton programme s'exécute, le CPU a un pointeur d'instruction qui pointe sur chaque instruction asm à exécuter, un peu à la manière de ce que tu vois quand tu steppes dans un débugger (et exactement ce que tu vois quand tu steppes dans un debugger désassembleur). L'idée est d'exploiter un bug du programme que tu as préalablement repéré (en général un buffer overrun d'un programme C ou C++) avec un désassembleur pour insérer dans le programme monté en RAM un bout de code qui va dévier le pointeur d'instruction vers du code à toi qui fera ce que tu veux. L'OS n'y voit que du feu, il ne peut empêcher que d'écrire dans la heap d'un autre programme, pas la modification du programme lui-même. Un prog C ou C++ peut fonctionner parfaitement et être malgré tout incorrect, et des bugs comme les buffer overruns sont des sources intarrissables d'attaques par les hackers. En particulier, les bugs de ce type sont particulièrement ennuyeux dans les logiciels qui ont un accès privilégié à l'OS parce qu'avec un shellcode, on peut prendre le contrôle de l'OS. Il y a cependant des techniques qui permettent de rendre la tâche considérablement plus difficile, entre autre la "randomisation" d'adresses qui fait que le programme chargé en mémoire n'a jamais le même layout 2 fois de suite et que le programme désassemblé. Cette technique est utilisée par le noyau Linux et Windows 7 en particulier.


Message édité par el muchacho le 15-04-2012 à 22:17:30

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 15-04-2012 à 23:01:45    

Oki, merci de l'info :D


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 16-04-2012 à 11:49:56    

Non mais y'a pas besoin de faire des bidouilles malsaines pour accéder à la mémoire d'un autre processus, sinon, ce serait une horreur de faire un Debugger. J'imagine qu'il y a une API système pour accéder à la mémoire d'un autre process et en mapper des portions dans l'espace d'adressage local, ca me paraitrait fou sinon.


---------------
last.fm
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed