web-dev-qa-db-fra.com

Comment vérifier les défaillances de l'allocation de mémoire avec le nouvel opérateur?

Juste récemment, j'ai changé la langue de mon projet pour utiliser C++ de C++ avec C, j'ai utilisé Malloc et après que je vérifie si Malloc a été réussi mais avec C++, j'utilise "nouveau" pour allouer la mémoire et je voudrais savoir comment vous Vérifierait normalement l'échec de l'allocation de la mémoire.

De ma recherche Google, j'ai vu rien comme ce qui suit.

char *buf = new (nothrow)char[10];

J'ai aussi vu ce qui suit.

try{} catch(bad_alloc&) {}

Mais qu'en est-il de ce qui suit? J'utilise une partie de chrome routines de bibliothèque pour utiliser des pointeurs intelligents.

Par exemple, j'ai le code comme suit.

scoped_array<char> buf(new char[MAX_BUF]);

C'est génial d'utiliser des pointeurs intelligents mais je ne suis tout simplement pas sûr de savoir comment je devrais vérifier si l'allocation de la mémoire a été réussie. Dois-je vous casser dans deux relevés distincts avec Nothow ou essayer/attraper? Comment faites-vous normalement ces chèques en C++?

Tout conseil sera apprécié.

27
istudy0

Eh bien, vous appelez nouveau que vous lancez bad_alloc, vous devez donc l'attraper:

try
{
    scoped_array<char> buf(new char[MAX_BUF]);
    ...
}
catch(std::bad_alloc&) 
{
    ...
}

ou

scoped_array<char> buf(new(nothrow) char[MAX_BUF]);
if(!buf)
{
   //allocation failed
}

Ce que je veux dire par ma réponse, c'est que les pointeurs intelligents propagent des exceptions. Donc, si vous allouez de la mémoire avec une lancée ordinaire, vous devez attraper une exception. Si vous allociez avec une nouvelle nouvelle, vous devez vérifier nullptr. En tout état de cause, les pointeurs intelligents n'ajoutent rien à cette logique

20
Armen Tsirunyan

Je déteste le dire, mais imo, tu vas dans la mauvaise direction (et, malheureusement, les autres réponses que vous avez obtenues ne vous ont pas vraiment signalé dans la bonne direction non plus).

Plutôt que de choisir entre différentes variétés de pointeur intelligent et/ou normales et de variantes NOthow de new, vous devriez probablement prendre au moins deux autres étapes de ce que vous faites, et Remplacez vos structures de données dynamiques gérées manuellement avec des collections. Cela peut ne pas toujours Soyez le bon choix, mais du moins de mon expérience, c'est la bonne façon d'aller un lot plus souvent que non. La bibliothèque standard présente un certain nombre de possibilités (vecteur, deque, liste, ensemble, etc.), etc.), et que des chances sont plutôt bonnes que vous pouvez utiliser l'un d'entre eux plutôt que de traiter directement avec new et une entreprise du tout.

Par défaut, ceux-ci utiliseront un allocator qui finit par utiliser la variante normale (lanceur) de new. Vous voulez donc normalement mettre la plupart des codes dans un bloc de try à un niveau assez élevé et avoir une clause catch qui traite d'avoir manqué de mémoire là-bas.

Lorsque/si vous avez besoin de faire face à une mémoire d'allocation directe, des chances sont plutôt bonnes que vous souhaitez toujours fournir une interface similaire à celle des conteneurs standard de la bibliothèque afin que cela fonctionne avec les algorithmes et les itérateurs normaux. Votre expérience initiale utilisant les conteneurs existants va payer de bien lorsque vous arrivez à ce point, même si cela peut être une façade de la route.

16
Jerry Coffin

En C++, il y a 2 façons principales dans lesquelles new alloue la mémoire et nécessite chacune une vérification erronée différente.

L'opérateur standard new lancera un std::bad_alloc Exception sur l'échec et cela peut être traité comme une exception normale

try {
  char* c = new char[100];
} catch (std::bad_alloc&) {
  // Handle error
}

Ou alternative la version nothrow de new va simplement revenir NULL sur échec

char* c = new (std::nothrow) char[100];
if (!c) {
  // Handle error
}

Je suis curieux de savoir ce que vous attendez de faire lorsque l'allocation échoue? S'il n'y a pas de mémoire disponible pour allouer votre objet, il y a souvent très peu de choses qui peuvent être faites dans le processus.

6
JaredPar

Vous aurez toujours besoin de vérifier un échec de l'allocation de mémoire.

Soit

scoped_array<char> buf;

try {
  buf.reset( new char[MAX_BUF] );
} catch( std::bad_alloc& ) {
  // Handle the failure
}

Ou

scoped_array<char> buf( new(std::nothrow)char[MAX_BUF] );

if( buf.get() == NULL ) {
   // Handle the failure
}
1
Praetorian