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

Langage C++ Discussion :

OpenGL et allocation dynamique


Sujet :

Langage C++

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2009
    Messages
    70
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2009
    Messages : 70
    Par défaut OpenGL et allocation dynamique
    Bonjour à tous,

    Je viens de tomber sur un drôle de problème, et j'aurais aimé savoir si quelqu'un a déjà recontré ce cas avec une autre librairie.

    Voici un code que j'ai ramené au plus simple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include <iostream>
     
    int 
    main (int argc, char * argv[])
    {
    	unsigned int * a = new unsigned int[16];
     
    	for ( unsigned int i = 0; i < 16; i++ )
    		std::cout << i << " : " << (unsigned int)a[i] << std::endl;
     
    	return 0;
    }
    Si je le compile en tant que projet C++ simple, j'ai une série de zéros qui s'affichent, comme ceci :

    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
     
    0 : 0
    1 : 0
    2 : 0
    3 : 0
    4 : 0
    5 : 0
    6 : 0
    7 : 0
    8 : 0
    9 : 0
    10 : 0
    11 : 0
    12 : 0
    13 : 0
    14 : 0
    15 : 0
    Mais si je rajoute au compilateur -lGL pour lier la bibliothèque d'OpenGL et sans rien modifier d'autre dans le code source, j'obtient ceci :

    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
     
    0 : 841837922
    1 : 775106862
    2 : 923430771
    3 : 909193830
    4 : 1701013045
    5 : 758132784
    6 : 825386551
    7 : 1667642678
    8 : 808464486
    9 : 757953056
    10 : 808460400
    11 : 808466480
    12 : 807415856
    13 : 825244216
    14 : 892613664
    15 : 808530231
    Et c'est la que je commence à ne plus rien comprendre ...

    Donc j'ai un projet utilisant OpenGL, et là ou je pensais allouer des valeurs à 0, je me retrouve avec de larges buffers pleins de valeurs à la noix, ce qui m'embête légèrement. Je peux toujours remettre des boucles un peu partout, mais je trouve ça tout même bizarre.
    L'opérateur new n'est pas censé initialiser les valeurs a 0 en toutes circonstances?

    Je suis sur une debian 64, avec le dernier pilote nvidia du site proprio (sans quoi pas de 3D).

    Voila, celui qui a une idée

  2. #2
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2011
    Messages
    59
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2011
    Messages : 59
    Par défaut
    Salut,

    contrairement à d'autres languages C++ (tout comme C ) ne garantissent pas l'initialisation de la mémoire allouée sur le tas ou la pile, seules les variables statiques sont initialisées à 0,

    Cdt

  3. #3
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 614
    Par défaut
    Salut,

    Comme l'a dit kessoufi, la mémoire alloué n'est pas initialisé. Elle vaut donc ce qu'il y avait dedans à ce moment là. Le fait que tu obtienne des zéros viens juste d'un gros coup de bol

  4. #4
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2009
    Messages
    70
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2009
    Messages : 70
    Par défaut
    Bon ben, je sais pas où j'ai pêché que new initialisait les valeurs a 0 alors... LOL

    Merci pour vos réponses.

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Bonjour,
    Une initialisation est possible :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned int * a = new unsigned int[16]();
    C'est bien une paire de parenthèse vide qui est nécessaire et provoque une initialisation à 0 (ou appel du constructeur par défaut pour une classe). Pour un tableau tu ne peux mettre de valeurs : unsigned int * a = new unsigned int[16](0); => erreur

    Ce qui donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <iostream>
     
    int 
    main (int argc, char * argv[])
    {
    	unsigned int * a = new unsigned int[16]();
     
    	for ( unsigned int i = 0; i < 16; i++ )
    		std::cout << i << " : " << a[i] << std::endl;
     
    	return 0;
    }
    On ne répétera jamais assez : std::vector à la place des allocations new[]/delete[] ... En plus tu peux initialiser avec une valeur spécifique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <iostream>
    #include <vector>
     
    int
    main (int argc, char * argv[])
    {
    	std::vector<unsigned int> a(16,42);
     
    	for ( unsigned int i = 0; i < 16; i++ )
    		std::cout << i << " : " << a[i] << std::endl;
     
    	return 0;
    }

  6. #6
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2009
    Messages
    70
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2009
    Messages : 70
    Par défaut
    Je ne connaissais pas les parenthèses vident avec l'allocation d'un tableau.

    Par contre, je ne pense pas que je vais pouvoir utiliser des std::vector partout. Parce que je dois créer des tableau de float (GLfloat pour être précis) et les fonctions de chargement d'OpenGL attendent des pointeurs du type "GLfloat *". J'ai pas vu de méthode comme pour std::string ou on sort un pointeur avec c_str() par exemple.

    Maintenant je penserais a std::vector dans tout les autres cas

    merci

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634

  8. #8
    screetch
    Invité(e)
    Par défaut
    (attention avec ce genre de blagues; un push_back et paf, ton pointeur a changé!)

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par screetch Voir le message
    (attention avec ce genre de blagues; un push_back et paf, ton pointeur a changé!)
    On est d'accord. Mais, un push_back supposerait avec des pointeurs bruts une réallocation. Donc, le problème serait le même.
    L'intérêt &[0] est bien de passer le tableau à une interface C le temps d'un traitement. Le pointeur (comme un itérateur) n'a pas vocation à être gardé.

  10. #10
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2009
    Messages
    70
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2009
    Messages : 70
    Par défaut
    D'accord, j'aurais même pas penser à faire comme avec un tableau classique.

    Bon ben j'en aurais appris des choses aujourd'hui avec cette mésaventure de new

    Sachant qu'il n'y a plus d'obstacle technique a l'emploi des std::vector. Une question me vient, cela vaut il la peine que je remplace mes new[]/delete[], si je sais qu'une fois alloués mes tableaux ne changeront plus jamais de taille?
    C'est généralement des énormes tableaux de floats pour afficher un objet en 3D.

    J'ai encore cette petite hésitation a me dire que je vais perdre en memoire/performance en utilisant des conteneurs plutot que du C classique.

    merci

  11. #11
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 614
    Par défaut
    Tu vas perdre 24 octets (à peu près) en utilisant un std::vector par rapport à un tableau classique, tu vas rien perdre niveau perf (peut être 1 ou 2 cycles lors de ton &[0]) et tu vas énormément gagner en facilité d'utilisation et en robustesse

    Alors 100000 fois oui pour utiliser un std::vector plustot qu'un tableau classique !

    A noté aussi que les conteneurs STL verifient les indices (à activer quelque part lors de la compilation mais je sais plus où ), donc plus de segfault intempestif parce que tu a dépassé ton tableau, à la place tu aura une jolie exception qui t'amènera directement au bon endroit

  12. #12
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2009
    Messages
    70
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Septembre 2009
    Messages : 70
    Par défaut
    Je m'attendais un peu a réponse comme ça

    ben ok, merci beaucoup.

  13. #13
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 28
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Bonjour à tous (pour mon premier message),
    c'est un peu en dehors du sujet initial mais ça ne vaut pas le coup de lancer un nouveau sujet. J'avais essayé cette méthode qui compilait correctement sur gcc
    mais lorsque j'avais essayé de compiler le même code sur Visual (version 8), il compilait mais le code plantait. Sur visual les vector ne seraient pas ré-implémentés ?

  14. #14
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 032
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 032
    Billets dans le blog
    12
    Par défaut
    Si ton tableau est de taille fixe un std::vector est tout indiqué. Si en plus tu connais sa taille à la compilation, tu peux utiliser std::array (C++0x), std::tr1::array (TR1) ou boost::array (si ni 0X ni TR1) qui te permettront de ne pas avoir l'overhead du std::vector (les 24 octets en plus).
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  15. #15
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 614
    Par défaut
    @arthurG
    Bien que le &a[0] ne soit pas dans la norme C98, je n'ai jamais vue d'implémentation qui l'interdisait...
    Ton vecteur n'est pas vide au moins ? Peut-tu nous montrer le code qui plante ?

  16. #16
    screetch
    Invité(e)
    Par défaut
    MSVC l'interdit
    When compiling with _SECURE_SCL 1, a runtime error will occur if you attempt to access an element outside the bounds of the vector. See Checked Iterators for more information.
    c'est un comportement indeterminé et sous MSVC ca produit une erreur, sous GCC ca compile et marche.

  17. #17
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 614
    Par défaut
    Ah, voila, le _SECURE_SCL c'est ce que je cherchait tout à l'heure pour fliquer les vecteur
    Par contre, ça n'explique pas pourquoi son &a[0] ne marche pas (sauf si le vecteur est vide, auquel cas, ça finira bien par faire un segfault même avec gcc)

  18. #18
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par norme C++98
    23.2.4 Class template vector [lib.vector]
    1 [...]The elements of a vector are stored contiguously, meaning that if v is a vector<T, Allocator> where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().
    Pour moi cela signifie de facto que que peut récupérer &v[0] et parcourir le tableau jusqu'à sa limite.

  19. #19
    screetch
    Invité(e)
    Par défaut
    &v[n] == &v[0] + n for all 0 <= n < v.size().
    ici on peut avoir v.size() == 0 donc n n'est pas strictement inférieur a v.size()
    si le vecteur est vide, v[0] est un comportement indeterminé (et donc par extension &v[0]) qui sous visual C++ ne fera pas le café mais lancera une assertion si _SECURE_SCL est défini

    c'est un cas particulier donc si le vecteur est vide.

  20. #20
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par arthurG Voir le message
    Bonjour à tous (pour mon premier message),
    c'est un peu en dehors du sujet initial mais ça ne vaut pas le coup de lancer un nouveau sujet. J'avais essayé cette méthode qui compilait correctement sur gcc
    mais lorsque j'avais essayé de compiler le même code sur Visual (version 8), il compilait mais le code plantait. Sur visual les vector ne seraient pas ré-implémentés ?
    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
    void fonction(unsigned * v, unsigned l)
    {
        for(;l>0;--l)
        {
            *v++=42;
        }
    }
     
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <iterator>
     
    int main ()
    {
        std::vector<unsigned int> a(16);
        fonction(&a[0],a.size());
        std::copy(a.begin(),a.end(),std::ostream_iterator<unsigned int>(std::cout,"\n"));
     
        return 0;
    }
    Compilé avec MinGW, Visual 2010 et Visual 2008

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. probleme d'allocation dynamique
    Par vince3320 dans le forum C
    Réponses: 10
    Dernier message: 22/04/2004, 16h27
  2. petit pbm allocation dynamique de stringGrid
    Par AnneOlga dans le forum C++Builder
    Réponses: 10
    Dernier message: 17/01/2004, 11h59
  3. Allocation dynamique de structures
    Par fr_knoxville dans le forum C
    Réponses: 8
    Dernier message: 06/05/2003, 21h59
  4. Allocation dynamique de mémoire en asm
    Par narmataru dans le forum Assembleur
    Réponses: 7
    Dernier message: 17/12/2002, 22h31
  5. Réponses: 4
    Dernier message: 03/12/2002, 16h47

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