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 :

Manipulation d'adresse de pointeur pour memcpy sans connaitre le type des données.


Sujet :

Langage C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Avril 2004
    Messages : 574
    Points : 109
    Points
    109
    Par défaut Manipulation d'adresse de pointeur pour memcpy sans connaitre le type des données.
    Bonjour,

    J'ai un petit soucis d'utilisation du C++, aussi comme c'est un cas un peu particulier, je voulais vous demandez votre avis :

    J'ai un tableau dans je ne connais pas le type (ça peut être MaClasse[4], comme float[6]... etc).

    Mais à aucun moment je ne sais quel est le type. Tout ce dont je dispose c'est :
    * sizeObj : la taille de l'objet (sizeof(MaClasse) ou sizeof(float) par exemple).
    * source : un void * pointant sur l'obj (mon tableau).
    * destination : un void * pointant sur l'obj (du type égal à ce qui est contenu dans le tableau (par exemple maClasse ou un float).

    J'aimerais faire un memcpy(destination, source, sizeObj) pour plusieurs élément du tableau à divers destination, mais il semble que le fait de ne pas connaitre le type de l'obj ne passe pas à la compilation...

    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
      for (unsigned l_ii = 0; l_ii < l_countInstance; l_ii++)
        {
          // Source pointer on the current value to copy
          void * l_val = new void*;
          // set the obj in l_val
          Get(l_val);       
          int * l_beginMem = (int *)l_val + (l_countInstance * l_sizeObj);
          
    
          // Destination pointer on child where copy value
          void * l_valChild = new void *;
          // Get the obj of destination
          m_children.at(l_ii)->Get(l_valChild);
    
          // Copy value 
          memcpy (l_valChild, l_beginMem, l_sizeObj);
    
        }
    J'ai le sentiment de ne pas posséder la bonne adresse au niveau de la ligne en bleu...

    En connaissant à l'avance le type, je peux caster void * l_val en Montype *, si cela peut vous aidez à comprendre.
    Comment manipuler seulement les adresses des endroits sources et destinations sans se préocuper du type des données, puisque je connais les tailles à copier?

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Comment manipuler seulement les adresses des endroits sources et destinations sans se préocuper du type des données, puisque je connais les tailles à copier?
    Heu, et comment vous gérez le padding entre les éléments du tableau si cous connaissez pas le type de l'élément ?

    La copie binaire d'objet, c'est plus que suspect.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Avril 2004
    Messages : 574
    Points : 109
    Points
    109
    Par défaut
    Ben en fait, du coup, je fais comme si j'avais des int ou des char. Dès que j'ai l'adresse en mémoire pour l'instant, je copie coup par coup. C'est pour cela je me demandais si il y avait quelque chose de plus élégant.


    en fait, c'est parce que je dois faire un programme générique capable d'envoyer des données binaires sur un réseau.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Il y a tout un tas de Framework qui gère la sérialisation pour ça, boost par exemple.
    Et des données opaques, c'est bien gentil, mais s'il y a des pointeurs dans les objets, bonjour les dégâts.

  5. #5
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par zuzuu Voir le message
    J'aimerais faire un memcpy(destination, source, sizeObj) pour plusieurs élément du tableau à divers destination, mais il semble que le fait de ne pas connaitre le type de l'obj ne passe pas à la compilation...
    Tu n'as pas le droit de faire memcpy sur des objets, sauf conditions spéciales. En C++98, les conditions sont que l'objet soit un POD (en gros, une struct à la C, dont tous les membres sont aussi des POD, aucun constructeur, pas de fonction virtuelle...). En C++0x, les conditions ont été légèrement relâchées (on peut avoir des contructeurs, mais les constructeurs de copie et de déplacement doivent être triviaux), mais il n'empêche que la grande majorité des types n'est pas compatible avec memcpy.

    Comme tu es dans la section .NET, je suppose que tu parles de C++/CLI, et non de C++, et bien là non plus les types ne sont pas copiables directement en mémoire, et pire encore, on ne peut même pas lire directement leur représentation mémoire, sans les avoir a préalable épinglé (pin) pour empêcher le GC de les bouger d'un point à l'autre...
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    574
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Avril 2004
    Messages : 574
    Points : 109
    Points
    109
    Par défaut
    Non, non , c'est bien du C++ que je fais. Je me suis trompée de rubrique ?
    En fait, c'est justement sur des structures que nous faisons cela uniquement. Justement, il semble que ce soit le seul moyen de pouvoir enregistrer bit à bit (ou octet par octet) les données et les récupérer ensuite pour reconstituer la structure d'origine.

  7. #7
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    En effet, ici, c'est pour la variante du C++ liée à .NET, c'est à dire le C++/CLI. Pour le C++, c'est http://www.developpez.net/forums/f19/c-cpp/cpp/
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  8. #8
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par zuzuu Voir le message
    Justement, il semble que ce soit le seul moyen de pouvoir enregistrer bit à bit (ou octet par octet) les données et les récupérer ensuite pour reconstituer la structure d'origine.
    Outre ce qu'à déjà précisé Loïc sur les contraintes de la structure pour garantir un memcpy 'brut' en C++, je voudrais juste rappeler qu'une bête sérialisation octet par octet pour transporter des données doit tenir compte (en C++ comme en C) des problèmes d'alignements, de boutisme, de taille des types et j'en oublie certainement.
    Je crois que si tu peux tu devrais suivre le conseil de bacelar et opter pour une bibliothèque qui propose de la sérialisation en C++.

    Sinon, sur le code que tu as posté :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void * l_val = new void*;
          // set the obj in l_val
          Get(l_val);
    ici tu alloue un pointeur sur void. Donc (en supposant que tu as des adresses sur 32 bits), tu alloues 4 octets seulement.
    Que fait Get ? S'il se contente de positionner l'adresse de l_val, alors l'allocation est inutile. S'il copie des données vers l'adresse pointée par l_val, alors tu auras souvent des débordements.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int * l_beginMem = (int *)l_val + (l_countInstance * l_sizeObj);
    En appliquant l'arithmétique des pointeurs, cette ligne ne déplace pas l_val de l_countInstance * l_sizeObj octets mais de (l_countInstance * l_sizeObj)*sizeof(int) octets puisque tu cast l_val en int*.

    Et bien sur il en va de même pour la variable suivante.

    Donc ta ligne bleu pose bien problème mais c'est probablement toute ta sérialisation qui risque de partir dans les choux.

Discussions similaires

  1. Réponses: 0
    Dernier message: 02/06/2010, 10h23
  2. Réponses: 8
    Dernier message: 26/05/2010, 14h43
  3. update sans connaitre le nom des tables
    Par Sinon dans le forum Langage SQL
    Réponses: 2
    Dernier message: 21/04/2010, 22h18
  4. Réponses: 5
    Dernier message: 30/09/2009, 19h51
  5. Réponses: 5
    Dernier message: 13/07/2008, 22h20

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