Question Comment vérifier les échecs d'allocation de mémoire avec un nouvel opérateur?


Tout récemment, j'ai changé la langue de mon projet pour utiliser C ++ à partir de C. Avec C, j'ai utilisé malloc et après cela, j'ai vérifié si malloc avait réussi, mais avec C ++, j'utilise 'new' pour allouer de la mémoire et j'aimerais savoir comment vérifier normalement l'échec de l'allocation de mémoire.

De ma recherche google, j'ai vu nothrow comme 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 certaines routines de la bibliothèque chrome 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 pas sûr de savoir comment vérifier si l'allocation de mémoire a réussi. Dois-je faire deux déclarations séparées avec nothrow ou try / catch? Comment faites-vous normalement ces vérifications en C ++?

Tout conseil sera apprécié.


22
2017-07-26 16:10


origine


Réponses:


Eh bien, vous appelez nouveau qui jette 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 un lancer ordinaire, vous devez attraper une exception. Si vous allouez avec un nouveau nodow, alors vous devez vérifier nullptr. Dans tous les cas, les pointeurs intelligents n’ajoutent rien à cette logique


17
2017-07-26 16:12



Je déteste le dire, mais à l’OMI, vous allez dans la mauvaise direction (et malheureusement, les autres réponses que vous avez reçues ne vous ont pas vraiment orienté dans la bonne direction).

Plutôt que de choisir entre différentes variétés de pointeurs intelligents et / ou de variantes normales ou décroissantes de new, vous devriez Probablement prenez au moins deux étapes de plus par rapport à ce que vous faites et remplacez vos structures de données dynamiques gérées manuellement par des collections. Cela peut ne pas toujours être le bon choix, mais au moins dans mon expérience, c'est la bonne façon de lot plus souvent qu'autrement. La bibliothèque standard offre un certain nombre de possibilités (vecteur, deque, liste, ensemble, etc.) et il est fort probable que vous puissiez en utiliser une plutôt que de traiter directement avec new et compagnie du tout.

Par défaut, ceux-ci utiliseront un allocateur qui utilisera la variante normale (de lancement) de new. Vous devez donc normalement mettre le plus de code dans un try bloquer à un niveau assez élevé, et avoir un catch clause qui concerne le manque de mémoire.

Si / si vous avez besoin d'affecter directement de la mémoire, il est fort probable que vous souhaitiez toujours fournir une interface similaire à celle des conteneurs standard de la bibliothèque pour qu'elle fonctionne avec les algorithmes et les itérateurs normaux. Votre expérience initiale d'utilisation des conteneurs existants sera rentable lorsque vous en arriverez à ce stade, même si cela peut s'avérer être une solution.


15
2017-07-26 17:27



En C ++, il existe 2 manières principales par lesquelles new alloue de la mémoire et chacune nécessite une vérification des erreurs différente.

Le standard new l'opérateur va lancer un std::bad_alloc exception en cas d'échec et cela peut être traité comme une exception normale

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

Ou alternative le nothrow version de new reviendra simplement NULL en cas d'échec

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

Je suis curieux quant à ce que vous vous attendez à faire lorsque la répartition échoue? S'il n'y a pas de mémoire disponible pour allouer votre objet, il y a souvent très peu de choses à faire dans le processus.


5
2017-07-26 16:15



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

Non plus

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
2017-07-26 16:17