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 :

Problème allocation mémoire


Sujet :

C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 8
    Points : 3
    Points
    3
    Par défaut Problème allocation mémoire
    Bonjour à tous,

    Je travaille sur un gros programme (sous Linux) qui alloue régulièrement (via new) des arrays de double d'environ 6 Mo (donc a priori pas rédhibitoires), et qui, après un certain temps de fonctionnement, me renvoyait une exception bad_alloc. J'ai donc géré l'exception via catch... throw, en retentant l'allocation mémoire jusqu'à ce qu'elle réussisse. Ca ressemble à ça.

    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
    	bool allocation_success = false;
    	while (!allocation_success)	
    	{
    		cerr << "Node::allocate_buffer | Allocating " << msg.total_size << " bytes" << endl;
    		try
    		{
    			msg.root = new char[msg.total_size];
    			if( msg.root )
    			{
    				allocation_success = true;
    				cerr << "Allocation done." << endl;
    			}
    			else
    				cerr << "Allocation failed ! Attempting again !" << endl;
    		}
    		catch (std::bad_alloc & e)
    		{
    			cerr << " Allocation failed ! Bad alloc received !" << std::endl;
    		}
    		catch(...)
    		{
    			cerr << " Allocation failed ! Standard notification." << std::endl;
    		}
    	}
    Mon problème, donc : quand il n'arrive pas à faire l'allocation, il boucle en permanence, ce qui donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Node::allocate_buffer | Allocating 6400024 bytes
     Allocation failed ! Bad alloc received !
    Node::allocate_buffer | Allocating 6400024 bytes
     Allocation failed ! Bad alloc received !
    ad libitum...

    L'état de ma mémoire à ce moment-là : sur 2 Go, 0.7 Go utilisés par le programme, 0.1 Go par le système, et 1.2 Go en cache. Et quasi zéro libre. Tout se passe donc comme si le prog n'arrivait pas à libérer le cache pour allouer mon vecteur.

    Voili voilou, je rame un peu et ne maîtrise pas encore bien la gestion mémoire, donc toute idée sur la cause de ce problème me serait d'une aide incomparablement kikoololfuntop.
    Bonne journée, et merci à ceux qui prendront le temps de me répondre ! Enjoy the day...

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 369
    Points
    50 369
    Par défaut
    Une possibilité : au bout d'un certain temps, ton tas est fractionné et il n'y a plus assez de gros blocs de mémoire disponibles pour permettre ton allocation

    Par contre, je ne sais pas comment on peut récupérer une indication du taux de fractionnement ni comment forcer le système à faire un peut de nettoyage dans le tas (pour autant que cela soit possible)

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    107
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 107
    Points : 122
    Points
    122
    Par défaut
    utilise valgrind (puisque t'es sous linux)

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

    Informations professionnelles :
    Activité : aucun

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

    Le plus vraisemblable, c'est que tu as sans doute des fuites mémoires de-ci de là...

    N'oublie pas que tout new doit être associé au delete correspondant, sous peine, justement, de voir des parties de mémoires considérées comme utilisées, alors que tu en as perdu toute trace dans ton programme.

    Aussi, il faut savoir que, dans l'absolu, si tu peux t'éviter les allocations de mémoire dynamique, c'est toujours un bon plan que de le faire.

    Ainsi, si tu as vraiment besoin de tableaux de taille importante, tu devrais peut être envisager de te tourner plutôt vers les classes de la STL telles que std::vector, qui, bien qu'elles utilisent aussi l'allocation dynamique pour leur fonctionnement interne, t'assure au moins que la mémoire - et principalement la libération de la mémoire allouée dynamiquement - sera gérée correctement

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 8
    Points : 3
    Points
    3
    Par défaut
    Merci pour ces réponses,

    En effet, j'ai pensé au départ à des fuites mémoires, que j'ai essayé de débusquer, mais il me semble que si ces ressources n'avaient pas été désallouées, elles apparaitraient dans la mémoire allouée au programme, et pas dans la RAM cache ?

    Le problème, en fait, est que j'ai besoin (ou me tromperais-je ?) d'une array puisque j'envoie le pointeur "associé" à un send dans un socket. Je ne peux donc pas vraiment me passer du new.
    ----
    Edit : Ou alors, puis-je écrire quelque chose comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int mon_array[2000];
    //Remplissage de l'array;
    int* pointeur_de_mon_array = mon_array;
    // send(pointeur_de_mon_array, vers peer)
    Je ne suis pas certain de la propreté de cette méthode, mais ça permettrait d'éliminer le new.

  6. #6
    Membre averti Avatar de vdumont
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 510
    Points : 369
    Points
    369
    Par défaut
    new alloue de la mémoire sur le heap (tas), tandis que int mon_array[1000] alloue de la mémoire sur le stack (pile).


    PS, lorsque l'opérateur new n'est pas capable d'allouer la demande de mémoire, il appel un new-handler repetitivement jusqu'a temps qu'il puisse trouver asser de mémoire. Donc tu pourrais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void outOfMemory()
    {
       std::cerr << "Manque de memoire\n";
       // tenter de rendre mémoire disponible
       // ou throw exception
       // ou abort/exit
    }
    et ensuite faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::set_new_handler(outOfMemory);

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 8
    Points : 3
    Points
    3
    Par défaut
    Et que se passe-t-il quand le prog essaie d'allouer sur le stack, mais qu'il n'a plus de mémoire ? Au moment où ma version actuelle (new int[1000]) renvoie std::bad_alloc, mon_array[1000] fonctionnerait-il ?

    Merci pour l'info sur le new_handler

  8. #8
    Membre averti Avatar de vdumont
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 510
    Points : 369
    Points
    369
    Par défaut
    Je crois que tu vas avoir un joli Segmentation fault.

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 8
    Points : 3
    Points
    3
    Par défaut
    Mouaif. Ca ne résoud donc pas mon problème... Je vais tester, merci en tout cas pour toutes ces réponses...

  10. #10
    Provisoirement toléré
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Points : 495
    Points
    495
    Par défaut
    Citation Envoyé par vdumont Voir le message
    Je crois que tu vas avoir un joli Segmentation fault.
    Dans le meilleur des cas, le problème est détecté et la Segmentation fault a lieu immédiatement (avant d'écraser des données).

    Sinon, en l'absence de mesures efficaces de détection du problème, la pile déborde sur d'autres données, en général le tas, l'état mémoire est corrompu, et le segfault peut en être la conséquence indirecte (mais des calculs erronés auront été effectués avant, et dans le pire des cas, des sorties incorrectes aussi).

  11. #11
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Salut,

    Pour réduire les problèmes liés à la fragmentation tu peux peut-être essayer par exemple nedmalloc.

    MAT.

  12. #12
    Membre confirmé Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Points : 496
    Points
    496
    Par défaut
    Si ton probleme proviens d'une fuite de memoire alors voir toutes solutions proposé ( garbage, soft de memleak...)
    Sinon, si tu jongles souvant avec des gros buffers et de meme taille tu peux implementer un magazin de buffer, qui t'offre la possibilité de demander des buffer, et des les liberer (pas de delete, mais modification de son etat). J'ai implementer cela pour un soft de traitement video sous Windows, car l'allocation d'une image prenais trop de temps.

  13. #13
    Provisoirement toléré
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Points : 495
    Points
    495
    Par défaut
    Citation Envoyé par themadmax Voir le message
    J'ai implementer cela pour un soft de traitement video sous Windows, car l'allocation d'une image prenais trop de temps.
    Et est très fortement non déterministe en temps d'exécution.

    Le "magasin" (j'aime bien ce terme mais il faut donner la version anglaise : allocation pool) a l'avantage d'éviter la fragmentation à un niveau : celui des objets en magasin.

    Par contre, la mémoire ainsi prise (par le magasin) n'est pas forcément récupérable, quand les clients ont ramené les objets au magasin, pour faire d'autres choses.

    (Les informations contenus dans ce messages peuvent être entièrement fausses.)

  14. #14
    Provisoirement toléré
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Points : 495
    Points
    495
    Par défaut
    Citation Envoyé par ram_0000 Voir le message
    comment forcer le système à faire un peut de nettoyage dans le tas (pour autant que cela soit possible)
    A quel type de nettoyage penses-tu?

    (Surtout, ne prend pas mon message pour une remise en cause de ce que tu affirmes.)

  15. #15
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    N'utilise pas new pour allouer des tableaux de taille dynamique.
    Utilise plutôt std::vector.

  16. #16
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 8
    Points : 3
    Points
    3
    Par défaut
    Une nouvelle journée commence, voilà où j'en suis :

    - Je n'ai pas trouvé de fuite de mémoire dans le programme ; qui plus est, la quantité de mémoire utilisée par le programme reste la même (~30%) sur 2 heures de fonctionnement en continu.

    - L'allocation qui renvoie bad_alloc est toujours la même, et correspond au char[] que j'envoie vers un send, c'est la raison pour laquelle je ne peux (à ma connaissance) pas me passer d'une array. Je ne peux donc pas me servir de std::vector.

    - Le temps d'allocation n'est pas vraiment un problème, et mon vecteur est "petit" (6 Mo), donc devrait se caser sans problème dans les 1.3 Go de RAM non utilisés.

    Je ne comprends donc pas pourquoi le vecteur n'arrive pas à être alloué, même quand je tente répétitivement l'opération...

  17. #17
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    - L'allocation qui renvoie bad_alloc est toujours la même, et correspond au char[] que j'envoie vers un send, c'est la raison pour laquelle je ne peux (à ma connaissance) pas me passer d'une array. Je ne peux donc pas me servir de std::vector.
    std::vector c'est la même chose qu'un tableau en mieux.
    Les données sont contiguës, tu peux parfaitement les utiliser avec send. (&v[0] te donne un pointeur vers le premier élément)

  18. #18
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 8
    Points : 3
    Points
    3
    Par défaut
    Au temps pour moi. Je vais tenter ça, je te tiens au courant de l'efficacité...

Discussions similaires

  1. Problème allocation mémoire
    Par Nico28 dans le forum Windows Forms
    Réponses: 0
    Dernier message: 16/07/2010, 15h04
  2. Problème allocation mémoire
    Par Hurin dans le forum Débuter
    Réponses: 7
    Dernier message: 05/02/2008, 00h03
  3. Problème allocation mémoire - malloc () 1Gb
    Par Gellius31 dans le forum Bibliothèque standard
    Réponses: 14
    Dernier message: 21/12/2007, 13h16
  4. Problème allocation mémoire
    Par Arnaud F. dans le forum C
    Réponses: 9
    Dernier message: 08/04/2007, 14h42
  5. problème allocation mémoire
    Par kinta dans le forum C++
    Réponses: 7
    Dernier message: 10/02/2006, 00h22

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