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 :

memcpy et stl incompatibles ?


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Inscrit en
    Février 2005
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 4
    Par défaut memcpy et stl incompatibles ?
    Bonjour a tous,
    Je viens vous embeter avec une petite colle que je n'ai toujours pas resolue. Il y a sans doute une erreur grosse comme une maison, mais impossible de la trouver...
    Il ne s'agit pas d'utiliser memcpy pour recopier des structures stl, ou des choses compliquees. Le probleme se pose lors de l'appel d'une methode stl sur un tableau recopie en utilisant la methode memcpy.


    Voici les deux fichiers composant mon projet :

    Photon.h : une classe simple contenant 3 flottants
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    #ifndef PHOTON_H
    #define PHOTON_H
     
    class Photon
    {
    public :
    	float position[3];
    	float direction[3];
    	float power[3];
    	float &x;
    	float &y; 
    	float &z;
     
    	Photon() : x(position[0]), y(position[1]), z(position[2])
    	{
    		position[0] = 0.0f;
    		position[1] = 0.0f;
    		position[2] = 0.0f;
    	}
     
    	Photon(Photon& p) : x(position[0]), y(position[1]), z(position[2])
    	{
    		position[0] = p.x;
    		position[1] = p.y;
    		position[2] = p.z;
    	}
     
    	Photon& operator=(const Photon&	p)
    	{
    		position[0] = p.x;
    		position[1] = p.y;
    		position[2] = p.z;
    		return *this;
    	}
     
    };
     
    #endif // PHOTON_H
    main.c : le code qui me pose une colle
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    #include <iostream>
    #include <algorithm>
    #include <functional>
    #include "Photon.h"
    
    using namespace std;
    
    #define ARRAY_SIZE 10
    
    template <class T> class CompareAlongDimension : public std::binary_function<T*, T*, bool>
    {
    public:
    	int dimension;
    	CompareAlongDimension( int d ) : dimension(d) {}
         bool operator()(T const & A, T const & B) { return A.position[dimension] < B.position[dimension]; }
    } ;
    
    void showPhotonArray(Photon* array, int axis){
    	for(unsigned int i = 0; i < ARRAY_SIZE; i++)
    	{
    		cout << array[i].position[axis] << " ";
    	}
    	cout << endl;
    }
    
    
    int main(int argc, char** argv)
    {
    
    	Photon* array = new Photon[ARRAY_SIZE];
    	Photon* copy = new Photon[ARRAY_SIZE];
    
    	for(unsigned int i=0;  i<ARRAY_SIZE; i++)
    	{
    		array[i].x = (float)rand()/(RAND_MAX+1);
    		array[i].y = (float)rand()/(RAND_MAX+1);
    		array[i].z = (float)rand()/(RAND_MAX+1);
    	}
    
    	//memcpy(copy, array, sizeof(Photon)*ARRAY_SIZE);
    	for(unsigned int i=0;  i<ARRAY_SIZE; i++)
    	{
    		copy[i] = array[i];
    	}
    
    	cout << "Tirage Aleatoire original : " << endl;
    	showPhotonArray(array, 0);
    	sort(array, array+ARRAY_SIZE, CompareAlongDimension<Photon>(0) );
    	cout << "Tirage Aleatoire trie : " << endl;
    	showPhotonArray(array, 0);
    	cout << endl;
    
    
    	cout << "Copie du tirage originale : " << endl;
    	showPhotonArray(copy, 0);
    	sort(copy, copy+ARRAY_SIZE, CompareAlongDimension<Photon>(0) );
    	cout << "Copie du tirage triee: " << endl;
    	showPhotonArray(copy, 0);
    
    	return 0;
    }
    L'application cree 10 Photons aleatoires, puis les reorganise en fonction de leur coordonnee suivant l'axe X. J'utilise pour cela stl::sort. Hors, si je copie le tirage aleatoire original, puis cherche a le trier de la meme facon, des choses magiques se passent...

    Si j'utilise une boucle for pour faire la recopie du tableau, j'obtiens la sortie logique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Tirage Aleatoire original :
    0.00125122 0.808716 0.350281 0.746582 0.71048 0.0149841 0.147308 0.445679 0.00891113 0.571167
    Tirage Aleatoire trie :
    0.00125122 0.00891113 0.0149841 0.147308 0.350281 0.445679 0.571167 0.71048 0.746582 0.808716
    
    Copie du tirage originale :
    0.00125122 0.808716 0.350281 0.746582 0.71048 0.0149841 0.147308 0.445679 0.00891113 0.571167
    Copie du tirage triee:
    0.00125122 0.00891113 0.0149841 0.147308 0.350281 0.445679 0.571167 0.71048 0.746582 0.808716
    Mais si j'utilise memcpy pour faire la recopie... le tri est fait n'importe comment :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Tirage Aleatoire original :
    0.00125122 0.808716 0.350281 0.746582 0.71048 0.0149841 0.147308 0.445679 0.00891113 0.571167
    Tirage Aleatoire trie :
    0.00125122 0.00891113 0.0149841 0.147308 0.350281 0.445679 0.571167 0.71048 0.746582 0.808716
    
    Copie du tirage originale :
    0.00125122 0.808716 0.350281 0.746582 0.71048 0.0149841 0.147308 0.445679 0.00891113 0.571167
    Copie du tirage triee:
    0.00125122 0.0149841 0.00891113 0.746582 0.147308 0.350281 0.445679 0.571167 0.808716 0.746582
    Je n'arrive pas du tout a voir de quoi cela pourrait venir... Pouvez vous m'aider ?
    Merci !

    Tan'

  2. #2
    Membre expérimenté
    Profil pro
    Dev
    Inscrit en
    Décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Décembre 2007
    Messages : 191
    Par défaut
    memcpy est une fonction C, il y a peut-être un souci avec des tableaux d'objets.

    Puisqu'on est dans la stl je te conseillerai d'utiliser un std::vector<Photon> pour tes tableaux. Il y a des fonctions intégrées pour faire des copies proprement.

    D'ailleurs : memcpy n'appelle certainement pas le constructeur des objets, alors que ta boucle for oui (elle utilise ton operator = ). Le problème vient probablement de là.

    De plus il n'y a quelquechose que je ne comprend pas bien : pour quoi tes variables membres x, y et z sont de type float& et pas simplement float ?

  3. #3
    Membre expérimenté
    Profil pro
    Dev
    Inscrit en
    Décembre 2007
    Messages
    191
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Décembre 2007
    Messages : 191
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Photon() : x(position[0]), y(position[1]), z(position[2])
    	{
    		position[0] = 0.0f;
    		position[1] = 0.0f;
    		position[2] = 0.0f;
    	}
    On m'a dit que les intialiseurs étaient exécuté avant le code du constructeur (ce qui semble logique). Donc il me semble que ton tableau position n'est pas initialisé lorsque tu attribues les valeurs à x, y et z :$ .

  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 : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    De plus il n'y a quelquechose que je ne comprend pas bien : pour quoi tes variables membres x, y et z sont de type float& et pas simplement float ?
    On m'a dit que les intialiseurs étaient exécuté avant le code du constructeur (ce qui semble logique). Donc il me semble que ton tableau position n'est pas initialisé lorsque tu attribues les valeurs à x, y et z :$ .
    C'est juste un raccourci syntaxique, pour les gens qui préfèrent écrire p.x plutôt que p.position[0]. Donc x, y et z sont des références simplement car elles ne servent que de raccourci pour accéder à position[0], position[1] et position[2]. La liste d'initialisation ne sert pas à initialiser leur valeur, mais à les faire pointer vers position[], donc peu importe que position[] soit initialisé ou non. D'ailleurs on ne peut initialiser une membre référence que dans la liste d'initialisation.

    Bref pas de souci de ce côté, le problème vient juste du fait que memcpy n'appelle pas le constructeur et que x, y et z ne sont jamais initialisés et pointent donc vers n'importe quoi. Utilise lputôt std::copy, ou mieux, std::vector pour tes tableaux.

  5. #5
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Juste en complément :
    • memcopy => copy bits à bits une zone mémoire vers une autre. Ainsi, les pointeurs et references pointerons exactement la même chose dans la zone copié que dans la zone d'originine => grosse erreur mémoire
    • std::copy => copy avec l'operateur = un ensemble d'objet vers un autre

  6. #6
    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
    Par défaut
    std::copy fait la copie avec le constructeur de copie, pas avec l'opérateur d'affectation...

Discussions similaires

  1. Probleme de Compilation de la STL
    Par stoluup dans le forum MFC
    Réponses: 3
    Dernier message: 05/05/2004, 17h25
  2. [LG]Problême "types incompatibles"
    Par pierrOPSG dans le forum Langage
    Réponses: 7
    Dernier message: 23/04/2004, 21h34
  3. [Socket]Incompatible type ?
    Par Edouard Kaiser dans le forum Réseau
    Réponses: 30
    Dernier message: 21/02/2004, 20h58
  4. STL : std::set problème avec insert ...
    Par Big K. dans le forum MFC
    Réponses: 13
    Dernier message: 08/11/2003, 01h02
  5. [Kylix] [BCB] pb avec la STL
    Par pykoon dans le forum EDI
    Réponses: 1
    Dernier message: 29/12/2002, 12h56

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