2008-10-27 7 views

Répondre

45

Selon la norme actuelle, nouvelle ne retourne jamaisNULL, il jette un std :: bad_alloc à la place. Si vous ne voulez pas lancer de nouveau (selon l'ancienne norme) mais plutôt retourner NULL vous devriez l'appeler en postfixant avec "(std :: nothrow)". dire

Foo* foo = new (std::nothrow) Foo; 

Bien sûr, si vous avez un toolchain très vieux ou peut-être cassé, il pourrait ne pas suivre la norme.

+0

« Il ne retourne jamais NULL » ... alors vous allez-y et vous contredisez :) en utilisant std :: nothrow fait la première partie de votre déclaration false :) –

+0

Il ne le rend pas faux, juste un peu inconsistant. La version "normale" de new ne renvoie jamais NULL. – Gorpik

+1

Cela ne ferait pas de mal de corriger la réponse! –

0

Habituellement, personne ne teste le retour de nouveau dans le nouveau code parce que Visual Studio se comporte maintenant comme le dit la norme.

Dans l'ancien code si un hack a été fait pour éviter de lancer alors vous feriez mieux de tester.

+0

Qu'en est-il de la question implicite que l'environnement était MS DevStudio? –

+0

Rien. Mais si Visual Studio n'avait pas reçu ce correctif alors l'affiche serait beaucoup moins susceptible d'être dans cette situation "Je ne vois généralement jamais de test pour le nouveau en C++". Alors je l'ai expliqué. –

4

Tout dépend de la version de C++ que le code cible. La spécification C++ depuis longtemps a maintenant déclaré que, par défaut au moins, les échecs dans new provoqueront une exception C++, donc tout code effectuant un test serait entièrement redondant. Aujourd'hui, la plupart des programmes de programmation ciblent également les systèmes d'exploitation de mémoire virtuelle où il est quasiment impossible de manquer de mémoire, et une condition de mémoire insuffisante est si fatale que laisser l'application tomber en panne lors de l'accès NULL suivant est un bon moyen. de terminer.

Son seul vraiment en programmation embarquée, où la gestion des exceptions est considérée comme étant trop de surcharge, et la mémoire est très limitée, que les programmeurs prennent la peine de vérifier les nouvelles défaillances.

+0

Attraper l'exception et enregistrer des données sur le disque, pourrait être un meilleur moyen que de laisser l'application plante ... –

+0

Mais comment? C++ moderne est plein de création d'objets partout. Quand un "nouveau" échoue, il est fortement attendu que d'autres tentatives de nouvelles échoueront également. Ce qui signifie qu'une tentative de conservation des données sur le disque échouera également. –

+1

"où il est presque impossible de manquer de mémoire" Je ne suis pas d'accord qu'il est facile de manquer de mémoire virtuelle sur un processus 32 bits - dans Windows vous obtenez seulement 2 Go d'espace d'adressage - tout domaine impliquant des données échantillonnées peut facilement remplir ceci ou le fragmenter menant à un échec d'allocation – morechilli

3

Comme cité here

« Dans compilateurs conformes à la norme ISO C, si la mémoire ne suffit pas pour l'attribution, le code génère une exception de type std :: bad_alloc. Tout code qui suit est avorté jusqu'à ce que le l'erreur est gérée dans un bloc try-catch ou le programme se ferme anormalement Le programme n'a pas besoin de vérifier la valeur du pointeur: si aucune exception n'a été levée, l'allocation a réussi.

7

Tout dépend de votre compilateur VC++ jusqu'à la version 6 donne NULL si le nouvel opérateur échoue, sur une application non MFC. Maintenant, le problème s'aggrave lorsque vous utilisez par exemple STL avec VC++ 6, car la STL va avec les standards qu'il ne testera jamais pour NULL quand il a besoin de mémoire, et devinez ce qui se passera dans des conditions de mémoire insuffisante. Pour tout le monde qui utilise encore VC++ 6 et STL, consultez cet article pour un correctif. Don't Let Memory Allocation Failures Crash Your Legacy STL Application

3
  1. new lancers francs std::bad_alloc par défaut. Si vous utilisez default, la recherche de null est obsolète, mais la gestion des exceptions est nécessaire.Ce comportement par défaut est compatible avec paradigme de sécurité C++ d'exception - il fournit généralement qu'un objet est soit construit ou non affecté

  2. si vous remplacez par défaut en utilisant new (std::nothrow), la vérification sur null est nécessaire. "Nouveau" alloue et valide les pages. Il est donc possible de manquer de mémoire, soit parce que vous n'avez plus de descripteur de page, soit parce qu'il n'y a pas de mémoire physique disponible.

  3. recherche la gestion de la mémoire de votre système d'exploitation. La machine de référence C/C++ ne sait pas comment votre système d'exploitation gère la mémoire, il n'est donc pas sûr de se fier uniquement à la langue. Par exemple d'allocation de mémoire qui a mal tourné, lisez sur C + malloc() Linux overcommit