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 :

tableau trop grand ?


Sujet :

C++

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 9
    Points : 5
    Points
    5
    Par défaut tableau trop grand ?
    Salut

    J'ai une classe CObjet qui contient un int*. Dans mon programme je remplie ce int* et j'alloue dynamiquement la mémoire avec realloc et avec cette fonction (je stocke des coordonnées de point d'une image):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void CObjet::Add(int* point)
    {
    	p = (int *)realloc(p, (nb_elt*2+2)*sizeof(int));
     
    	*(p+(nb_elt*2)) = *point;
    	*(p+(nb_elt*2)+1) = *(point+1);
    	nb_elt++;
     }
    Ca marche très bien mais ca foire quand il y a trop de valeur à insérer dans le tableau (vers 12000 int). Il met en mode debug "Unhandled exception in X.exe : acces violation" et se plante après le realloc de trop.
    C'est le pointeur p retourné par realloc qui vaut NULL, mais je ne comprend pas pourquoi !? Je n'ai quand même pas atteind la taille limite de mémoire ?

    Merci d'avance


    [Balises CODE rajoutées par Loulou24, merci d'y penser à l'avenir]

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Hmm... On ne devrait plus voir ce genre de code en C++

    http://c.developpez.com/faq/cpp/?page=STL#STL_vector

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 9
    Points : 5
    Points
    5
    Par défaut
    Merci, mais je viens d'essayer la et je retombe sur le même problème. En plus c'est carément plus long avec des vectors en temps d'excécution (ou alors je m'y prend mal)

  4. #4
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Oui effectivement c'est bizarre, tu peux préciser ton environnement ?

    Sinon je pense que tu t'y prends mal avec les vector, car ça ne devrait pas être plus lent. Au pire montre nous les bouts de code qui seraient plus lent, on pourra te donner un avis.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 9
    Points : 5
    Points
    5
    Par défaut
    Je suis sous VC++ 6 et c'est un projet en mfc.
    Donc ma fonction ajouter d'en haut donne ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void CObjet::Add(int* point)
    {
    	p.push_back(*point);
    	p.push_back(*(point+1));
    	nb_elt++;
    }
    Je pense que c'est celle la qui fait tout ramer car j'y fais appel moulte fois pendant l'execution.
    Et d'ailleurs j'ai une question en passant, un push_back ca rempli le tableau par la fin, mais est ce qu'il faut inverser l'indice entre [] quand on veut avoir accès à une valeur avec l'opérateur [] (quand on fait MonVecteur[i]) ?

    Ah oui, j'ai essayé avec un pointeur sur des short int (2 octets au lieu de4 pour les int) et c'est exactement pareil ....


    [Balises CODE rajoutées par Loulou24, merci d'y penser à l'avenir]

  6. #6
    Membre habitué Avatar de PINGOUIN_GEANT
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 149
    Points : 155
    Points
    155
    Par défaut
    pour le code C realloc qui renvoie un pointeur NULL signifie sans doute que l'allocation a échoué.
    serait-il possible qu'il y ait un problème de contiguité de la mémoire ?
    " Tout homme est digne d'un parapluie." Stavroguine dans Les Démons de Dostoïevski.

  7. #7
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut


    push_back va au pire faire un realloc comme tu le faisais, au mieux il ne fera qu'ajouter l'élément (la mémoire est allouée exponentiellement, càd pas à chaque fois). Donc difficile de se dire que c'est plus lent.

    Pour ce qui est des indices... Forcément, si tu stockes un élément à la fin avec push_back il n'aura pas 0 comme indice.

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 9
    Points : 5
    Points
    5
    Par défaut
    Désolé pour les balises je ne recommencerai plus
    Merci pour ces éclaircissements sur les vectors.
    Mais expliquez vous que j'ai le même problème avec un pointeur de short int ? Normalement il devrait y avoir 2 fois moins de mémoire alloué qu'avec des int ? Mais le truc bloque toujours au même endroit (après 12000 coordonnées environ).
    Et quand tu parles de contiguité de la mémoire, ca veut dire quoi exactement, que la mémoire est dispersée ?

  9. #9
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Un vector ou un tableau dynamique classique alloue sa mémoire de manière contigüe. Donc s'il n'y a pas un tel espace contigüe disponible en mémoire, l'allocation echoue.
    Mais ne pas avoir 48000 octets libres contigüs en mémoire, c'est tout de même rare...

    Surtout que ça n'a pas l'air d'être lié à l'espace mémoire, mais plutôt au nombre d'éléments. Peut-être que l'erreur vient d'ailleurs ? Un ocmportement indeterminé qui viendrait empiéter sur ton espace mémoire ?

  10. #10
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 9
    Points : 5
    Points
    5
    Par défaut
    En fait je me demandais si ça venait pas du fait que le CObjet que je rempli (et qui explose la mémoire) est déclaré en variable globale (oui c'est pas top top mais je suis obligé de faire come ça). Est ce que ça change quelque chose dans le gestion de la mémoire ?

  11. #11
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Non cela n'a a priori rien à voir, car même si ton CObjet est déclaré en global, le pointeur p lui pointe bien sur un espace alloué sur le tas.

  12. #12
    Membre émérite
    Avatar de Ti-R
    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Avril 2003
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 683
    Points : 2 568
    Points
    2 568
    Par défaut
    Burk c'est pas beau un realloc....

    Il faut remplacer par quelque chose d'autre, et penser autrement...

    J'espère que tu ne mélanges pas new, delete et realloc...

    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
     
     
    // p doit être initialisé au départ à size_max
    void CObjet::Add(int* point) 
    { 
    	nb_elt++; 
    	if(nb_elt>=size_max)
    	{
    		size_max*=2; // peut être remplacer par une valeur comme "size_max+=5000;"
     
    		int *t_p = new int[size_max]; 
    		memcpy(t_p,p,nb_elt);
    		delete [] p;
    		p=t_p;
    		pt_p=p+nb_elt-1; // à vérifier si c’est bien -1 :)
    	}
     
    	*(pt_p++) = *point; 
    	*(pt_p++) = *(point+1); 
    }
    Bon et bien c'est un code à vérifier je pense, mais tu devrais augmenter les performances et ne plus avoir de bugs.

  13. #13
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Personnellement je préférais ce code-ci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void CObjet::Add(int* point)
    {
       p.push_back(*point);
       p.push_back(*(point+1));
       nb_elt++;
    }
    Mais apparemment cela n'a pas résolu le problème.

  14. #14
    Membre émérite
    Avatar de Ti-R
    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Avril 2003
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2003
    Messages : 1 683
    Points : 2 568
    Points
    2 568
    Par défaut
    Disons que c'est plus propre, mais cela n'assure forcément pas la vitesse d'exécution..., si besoin de vitesse il y a... Dans le meilleur des cas, cela fait quasiment la même chose dans l’allocation, un coût supérieur pour l’accès, mais le parcours du tableau ne peut être que de vitesse inférieure de toute façon.

    Enfin c'est le côté C de ma personne qui ressort

  15. #15
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Il ne sert à rien de réinventer des roues qui ne résistent pas aux exceptions aujourd'hui
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  16. #16
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Citation Envoyé par Ti-R
    Disons que c'est plus propre, mais cela n'assure forcément pas la vitesse d'exécution..., si besoin de vitesse il y a... Dans le meilleur des cas, cela fait quasiment la même chose dans l’allocation, un coût supérieur pour l’accès, mais le parcours du tableau ne peut être que de vitesse inférieure de toute façon.

    Enfin c'est le côté C de ma personne qui ressort
    Bah... Déjà comme le dit Luc ce sera bien plus fiable et sécurisé comme code. Ensuite, cela fera beaucoup mieux au niveau de l'allocation (la plupart des gens utilisent une stratégie de réallocation naïve -- en temps linéaire), et l'accès se ne se fera pas plus lentement (fonctions inlines). Pareil pour le parcours, un compilo qui optimise un minimum ne verra pas la différence.

    Enfin bref, c'était juste pour dire...

  17. #17
    Membre actif
    Profil pro
    Inscrit en
    Août 2003
    Messages
    247
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 247
    Points : 276
    Points
    276
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void CObjet::Add(int* point) 
    { 
       p.push_back(*point); 
       p.push_back(*(point+1)); 
       nb_elt++; 
    }

    Je trouve que c'est pas terrible comme fonction... (Pointeur null, point[1] alloué ?, etc)

    En C++, on définirait un type point et on paserait le paramètre par référence. (Apparemment, les deux éléments de ton tableau sont deux coordonnées.)

    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
     
    struct point
    {
     
    	int x, y;
     
    	point ( int a, int b ) : x(a), y(b) { }
     
    }
     
     
    typedef std::vector<point> CObject;
     
    // Que l'on utilise simplement ainsi:
     
    CObject a;
    a.push_back( point( 1, 5 ) );

    Ceci a l'avantage d'être rapidement fait et de disposer de toutes les fonctions de la STL: itérateurs, algorithmes, etc.

    Si std::vector n'est pas suffisant pour tes besoins et si CObject est intrinsèquement un conteneur, tu aura intérèt à faire dériver CObject de std::vector.

  18. #18
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 9
    Points : 5
    Points
    5
    Par défaut
    Ok merci tout le monde. J'ai pu (enfin !) résoudre mon problème.
    Ce que j'ai fait c'est alloué au départ un gros tableau démesuré de short int au départ. Une fois rempli, je construit un nouvel objet en allouant cette fois la bonne taille de short int vu que je connais le nombre d'élément. Ensuite je libère la mémoire du gros tableau avec un delete. J'ai rencontré aussi un problème de stack overflow (à cause d'une fonction récursive) que j'ai résolu. Alors je sais pas si ca a joué dans mon problème de mémoire mais toujours est il que ca marche !!!
    Selenite, j'avais fais ça au départ avec la classe point mais j'ai changé car je croyais que mon problème venait de ça. Mais je vais peut etre y revenir car c'est carément plus lisible !
    En tout merci infiniment à tous !

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

Discussions similaires

  1. Tableau trop grand : quelles alternatives?
    Par timbrochier dans le forum Collection et Stream
    Réponses: 14
    Dernier message: 14/08/2009, 14h46
  2. Tableau trop grand
    Par dannhil dans le forum Tableaux - Graphiques - Images - Flottants
    Réponses: 14
    Dernier message: 20/10/2008, 02h36
  3. Tableau trop grand sur FF
    Par kevinf dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 28/06/2008, 20h16
  4. taille tableau trop grande
    Par zhao dans le forum C++
    Réponses: 12
    Dernier message: 26/03/2008, 15h59
  5. [VBA-W2007]scinder automatiquement un tableau trop grand
    Par tazamorte dans le forum VBA Word
    Réponses: 3
    Dernier message: 22/06/2007, 17h28

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