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 :

Besoin d'aide avec Exception std::bad_alloc


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Août 2011
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2011
    Messages : 55
    Points : 32
    Points
    32
    Par défaut Besoin d'aide avec Exception std::bad_alloc
    Bonjour,

    Je cherche à déterminer les points qui compose une sphère voici ma fonction :
    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
    26
    27
    28
    29
    30
    std::vector<char> MaClasse::generateSphere(float diametre, float orgX, float orgY, float orgZ)
    {
        std::vector<char> liste;
        char inSphere;
        int y, z;
    	/*		y
    	 * 		|_x
    	 * 	       /
    	 * 	     z
    	 * */
     
        for(int x = orgX; x < diametre; x = x + 2)
        {
            for(y = orgY; y < diametre; y = y + 2)
            {
                for(z = orgZ; z < diametre; z = z + 2)
                {
    		inSphere = isInSphere(diametre, abs(orgX - x), abs(orgY - y), abs(orgZ - z));
    		liste.push_back(inSphere); // 0 ou 1
                }
            }
        }
     
        return liste;
    }
     
    char MaClasse::isInSphere(float diametre, float x, float y, float z)
    {
        return square(x) + square(y) + square(z) <= square(diametre);
    }
    Lorsque je lance l’exécution avec un diamètre de 10 000 000 (pas de restriction sur le temps de calcul), j'obtiens l'exception std::bad_alloc...

    Comment puis je faire pour obtenir tous mes points ?

    Merci

    Ps : J'ai essayé d'obtenir que le quart de ma sphère et ensuite effectué une symétrie,mais j'ai la même exception qui se lève...

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    pour 10 000 000 tu auras jusque 5 000 000 * 5 000 000 * 5 000 000 de push_back...
    Ta liste finale devrait faire jusque 5 000 000 * 5 000 000 * 5 000 000 de char, ce qui est une taille déjà extraordinaire.
    Mais en plus, le push_back doit réallouer une mémoire plus grande quand le push_back arrive au bout de l'allocation déjà faite.
    Potentiellement à un moment on se retrouve avec une liste de bcp trop de millions + encore plus de millions char.
    Inutile d'être un grand mathématicien pour supposer que c'est bcp trop de mémoires demandée.

    Btw, une bonne pratique avec vector (que l'on retrouve dans un bon millier de posts sur ce forum, surement en faq etc...) c'est re faire un reserve avant les push_back.

    Une autre bonne idée serait d'oublier l'idée saugrenue de vouloir une sphère de 10 000 000 de diamètre.
    Ou tout simplement ne pas créer (Diamètre/2)^3 char. A quoi peut bien servir cette liste ?!

    La réponse est simple : tu ne pourras jamais avoir autant de "points".
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

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

    Informations professionnelles :
    Activité : aucun

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

    L'exception std:: bad_alloc t'indique que "désolé mon p'tit gars, mais le système ne dispose pas d'assez de mémoire pour te fournir un espace contigu suffisamment grand pour te permettre de représenter en mémoire ce que tu demande".

    Autrement dit, tu atteints les limites de ce que le système est susceptible de supporter.

    Il peut y avoir plusieurs raisons à cela:

    L'architecture cible de ton programme limite la taille de mémoire disponible (par exemple, tu ne peux pas utiliser 2Go de mémoire avec une applications 32 bits sous windows)

    Le mode de fonctionnement de la collection que tu utilises fait qu'il y a un moment où le système a (temporairement) besoin d'un surplus d'espace libre.

    Tu essayes de manipuler un nombre décidément trop important de données.

    Vu que tu utilises un vecteur de char, je dirais que les deux raisons les plus vraisemblables sont la première et la deuxième

    En effet, si tu compiles ton application en mode 32 bits, tu subira "de plein fouet" la limite imposée de ne pas dépasser les 2Gb d'espace mémoire alloués à une seule et même application.

    Le fait de veiller à compiler ton application en 64 bits (si tant est que tu puisses le faire et utiliser une application 32 bits) pourrait te permettre de résoudre "temporairement" le problème.

    Si je parle de le résoudre "temporairement", c'est, tout simplement, parce qu'il peut parfaitement arriver un moment où les restrictions imposées aux applications 64 bits risquent de te rattraper

    Ce sera peut etre à 100 millions, peut etre à 30 milliards (ou à 300), mais, tôt ou tard, le système risque de te dire qu'il ne dispose pas d'assez d'espace mémoire

    Pour comprendre la deuxième raison, il faut savoir comment fonctionne la classe std::vector.

    Elle nous garanti en effet que les éléments seront contigus en mémoire, ce qui fait que, si tu as besoin de l'espace nécessaire pour représenter 10 000 00 de caractères, il faut trouver un espace mémoire égal à 10 Mb (enfin, à peine moins ) qui ne sont pas utilisés.

    Le problème, c'est que tu as trois boucles imbriquées, ce qui fait que tu vas devoir trouver d'autant plus de mémoire pour travailler

    Tu comprendras tout de suite qu'il est déjà difficile de trouver toute cette mémoire disponible en une seule fois

    Mais là n'est pas le seul problème!!!

    En effet, la classe vector va devoir régulièrement augmenter l'espace mémoire dont elle dispose (à l'occasion du push_back).

    Et pour garantir que les données reste contigües en mémoire, elle vas travailler dans un ordre proche de
    1. demander l'allocation dynamique d'une taille supérieure à la taille actuelle (souvent 1.5 * la taille actuelle il me semble)
    2. copier l'ensemble du contenu actuel dans l'espace mémoire dont elle vient de demander l'allocation dynamique
    3. libérer l'espace mémoire "d'origine"
    4. considérer le nouvel espace mémoire comme étant celui qui contient les données
    Cela signifie que, de l'étape 1 à l'étape 3, il faudra que le système ait trouvé (peu ou prou) 2,5 fois l'espace mémoire suffisant pour représenter tous les élément du vecteur, alors que je viens d'attirer ton attention sur le fait qu'il risque, déjà, d'avoir du mal à trouver l'espace mémoire suffisant pour représenter tous les éléments!!!

    Tu comprendras qu'il n'est pas particulièrement étonnant que le système se plaigne, à un moment ou à un autre, de ne plus trouver assez de mémoire

    D'autres collections (je penses en particulier à std:: list ) ne posent pas ce problème car chaque élément est relié à l'élément suivant.

    Cela permet de se contenter d'un espace mémoire suffisant pour représenter un pointeur (vers l'élément suivant) + l'espace mémoire pour représenter l'élément en question, mais...:
    • Déjà, les données ne sont plus contigues en mémoire (ou, du moins, on n'a strictement aucune garantie qu'elles le soient)
    • Etant donné que tes données "significatives" sont des char, cela implique que la taille du lien vers l'élément suivant est plus importante que celle de la donnée que tu veux placer dans la liste
    • Pour pouvoir accéder au 10 000 000 eme element, tu auras du parcourir les 9 999 999 premiers

    Au final, et malgré ce que je disais au début de mon intervention, on en revient à la troisième raison, quel que soit la solution envisagée: il semblerait que tu essayes définitivement de gérer trop de données d'un coup

    Es tu sur qu'il faille d'office l'ensemble des différents éléments

    Ne pourrais tu pas envisager de travailler par "secteurs" voir par "couche" de ta sphère

    Cela nécessiterait sans doute des temps de chargements et ou de calcul entre différents secteurs ou couches, mais ca te permettrait très certainement de limiter le nombre d'éléments à gérer "en même temps"
    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

Discussions similaires

  1. Besoin d'aide avec Regexp::Assemble
    Par mobscene dans le forum Modules
    Réponses: 5
    Dernier message: 11/04/2007, 12h39
  2. [ASA] J'ai besoin d'aide avec sybase et vb6 svp !!
    Par tibo830 dans le forum SQL Anywhere
    Réponses: 7
    Dernier message: 12/05/2006, 10h09
  3. Besoin d'aide avec TinyXML
    Par Clad3 dans le forum Bibliothèques
    Réponses: 5
    Dernier message: 15/08/2005, 18h20
  4. Réponses: 2
    Dernier message: 29/08/2003, 17h52
  5. Besoin d'aide avec postgresql sous windows NT
    Par Chihuahua dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 18/07/2003, 08h29

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