IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

std::bad_alloc est-elle bien utile…


Sujet :

C++

  1. #1
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut std::bad_alloc est-elle bien utile…
    Je viens de faire un test tout simple afin de vérifier/modifier certaines habitudes de codage, du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    			try
    			{
    				voidptr = ::operator new(stupid_big_value);
    				if (voidptr)
    					...;
    			}
    			catch (std::bad_alloc &)
    			{
    				...
    			}
    Sous Windows et Visual Studio 2015, machine avec 8GB de mémoire physique, j'ai alloué quelques terrabytes...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    stupid_big_value = 8ull * 1024 * 1024 * 1024 * 65536;
    ... Et aucune exception n'est levée

    Certains diront que c'est normal, la mémoire (virtuelle) est réservée mais non commitée.
    Je n'ose pas faire un memset(voidptr, 0, stupid_big_value), mais ce serait amusant de voir quand le système se fige...

    En bref, à quoi bon perdre son temps à essayer de récupérer un std::bad_alloc ou vérifier la nullité d'un pointeur après allocation, si, à priori, la mémoire est toujours "allouée".

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,

    Je me suis amusé il y a peu à voir la taille la plus grande que le système était prêt à m'allouer pour un std::vector sous linux (avec seulement 6 Gb de mémoire et 2Gb de swap ) pour y placer les différents types primitifs, et cette taille va de std::numeric_limits<std::ptr_t>::max() à std::numeric_limits<std::ptr_t>::max()/2, ce qui implique que la taille susceptible d'être allouée dépend de la première limite atteinte entre l'ensemble de la mémoire disponible et le nombre d'adresses devant être représentées

    Il faut cependant garder en tête qu'une application n'est que rarement seule à fonctionner sur un ordinateur, et que l'utilisation de la mémoire (physique et virtuelle) dépend de ce que font toutes les applications qui tournent à un instant T de l'utilisation de ton ordinateur

    Pour moi, manière générale, si une exception de type bad_alloc a été lancée, le mieux que tu aies à faire est sans doute encore de laisser planter correctement l'application, sans essayer de résoudre le problème : il se peut que ton application (celle dans laquelle l'allocation échoue) n'utilise que très peu de mémoire allouée dynamiquement, mais que le système en ait -- tout simplement -- donné tellement à d'autres applications qu'il n'est purement et simplement plus en mesure d'en donner la moindre parcelle à aucune application

    Cependant, je conçois aussi que l'on peut vouloir faire "quelque chose" avant de laisser planter l'application, par exemple, en sauvegardant son dernier état valide (qui correspond peut être à l'état de l'application juste avant que bad_alloc ne soit lancé). Cela ne devrait cependant pas t'empêcher de relancer l'excetpion pour faire en sorte que l'application s'arrête
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Ce code, appelé directement depuis le main(), Visual Studio 2013 Pro:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #include <climits>
    #include <memory>
    #include <iostream>
    using namespace std;
     
    void TestAlloc()
    {
    	cout << (sizeof(void*)*CHAR_BIT) << " bits." << endl;
    	size_t stupid_big_value = 8ull * 1024 * 1024 * 1024 * 65536;
    	try
    	{
    		void* voidptr = ::operator new(stupid_big_value);
    		if (voidptr)
    		{
    			cout << "Allocation successful." << endl;
    			::operator delete(voidptr);
    		}
    		else
    			cout << "Operator new returned nullptr instead of throwing." << endl;
    	}
    	catch (bad_alloc const &)
    	{
    		cout << "Operator new threw bad_alloc." << endl;
    	}
    }
    Résultat en Debug Win32 et Release Win32 (avec warnings à la compilation parce que ça tronque la taille, qui se retrouve à zéro):
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    32 bits.
    Allocation successful.
    Résultat en Debug x64 et Release x64:
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    64 bits.
    Operator new threw bad_alloc.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Le fait qu'il n'y ai pas d'exception pour les grosses allocations vient d'une option kernel (et probablement de la bibliothèque d’allocation sous-jacente).

    Sous Linux par exemple, certaines implémentations de malloc refilent toujours un pointeur valide qui réservera la mémoire à la première utilisation. Résultat, l'allocateur ne sais pas que le pointeur est invalide et l'utilisateur va faire planter son application¹ à la première utilisation du pointeur en accédant une zone mémoire qui ne lui ai pas attribué.

    ¹ Ou une application au hasard avec l'OOM Killer.

  5. #5
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    Merci à tous pour vos réponses.

    Je ne comprends pas ce qui s'est passé: la semaine dernière aucune exception n'était levée, et maintenant bien...
    Que s'est-il passé passé entre les deux ?
    Rien... si ce n'est le WE et que tout le monde s'est reposé, y compris mon ordi

    Bref, désolé de vous avoir dérangé. Maitenant j'ai bien un bad_alloc.
    Mais je risque d'encore me retourner dans mon lit pendant quelques nuits à me demander pq je n'en avais pas...

  6. #6
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    Vu la taille de l'allocation, je pencherais pour une allocation échouant à cause de la fragmentation de la mémoire. Qui varie d'un état à l'autre de la machine, sachant qu'il s'agit d'une allocation contiguë en mémoire.
    Homer J. Simpson


+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. La refactorisation est-elle réellement utile ?
    Par Amine Horseman dans le forum Débats sur le développement - Le Best Of
    Réponses: 43
    Dernier message: 25/06/2015, 08h41
  2. [Carte graphique] la HD5870 est elle bien nécessaire
    Par zooffy dans le forum Composants
    Réponses: 6
    Dernier message: 29/10/2009, 09h21
  3. JavaDoc : cette classe est elle bien commentée ?
    Par jmnicolas dans le forum Langage
    Réponses: 4
    Dernier message: 04/09/2008, 11h36
  4. InterpN est elle bien incomprehensible ?
    Par sayag dans le forum MATLAB
    Réponses: 1
    Dernier message: 29/06/2007, 08h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo