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 :

Serialisation d'objets complexes avec mmap


Sujet :

C++

  1. #1
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 2
    Par défaut Serialisation d'objets complexes avec mmap
    Bonjour,
    Comme le titre l'indique je cherche à sérialiser des objets complexes en utilisant mmap (et non pas boost, ou fstream dans un soucis de hautes performances). Par objets complexes j'entends par là des objets contenant des pointeurs (une structure d'arbre par exemple).
    J'ai beau chercher sur internet des exemples d'utilisation de mmap, je n'ai rien trouvé de mieux que des exemples de sérialisation d'un int ...

    L'idée serait de pouvoir par la suite récupérer ma structure simplement avec une ligne du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ma_structure obj = (ma_structure)mmap(...)
    Mais comment écrire l'objet dans le fichier à mapper ?

    Merci

  2. #2
    Membre Expert
    Avatar de skeud
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2011
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 1 091
    Billets dans le blog
    1
    Par défaut
    Etant donné que ton objet est une zone mémoire, il suffit juste de savoir la taille de cette zone de mémoire et l'écrire dans un fichier via write.

    Exemple:

    la structure:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct s_donnee
    {
       int code;
       int dataSize;
       bool valider;
       char* data;
    }
    l'écriture dans le fichier:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct s_donnee *don = new struct s_donnee;
    don->data = "coucou le petit lapin";
    don->dataSize = strlen(don->data);
    write(fd, don, sizeof(*don)+don->dataSize*sizeof(*(don->data)));
    ensuite tu pourra directement faire ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    struct s_donnee* don = new struct s_donnee;
    read(fd, don, sizeof(*don));
    read(fd, don->data, don->dataSize*sizeof(*(don->dataSize)));
    concernant mmap, je pense que tu peux directement faire un:
    Mais j'en suis pas sur, je laisse un membre plus confirmer ou internet te guider .


    EDIT: Tout ce que je dis là n'est pas bon, voir un message plus bas ou le code est correct .

  3. #3
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Par défaut
    Citation Envoyé par skeud Voir le message
    la structure:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct s_donnee
    {
       int code;
       int dataSize;
       bool valider;
       char* data;
    }
    l'écriture dans le fichier:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct s_donnee *don = new struct s_donnee;
    don->data = "coucou le petit lapin";
    don->dataSize = strlen(don->data);
    write(fd, don, sizeof(*don)+don->dataSize*sizeof(*(don->data)));
    Pas sûr que ça fonctionne ... s_donnee::data est un pointeur sur char et non un tableau, son contenu ("coucou le petit lapin") n'est pas dans la structure mais alloué dans une zone mémoire à part (dans la section .rodata du binaire par exemple). Pour ça il faudrait déclarer data de type char[SOME_SIZE] et copier le contenu de la chaîne "coucou le petit lapin" dans ce tableau. Remarque au passage, la taille de ce tableau est prise en compte dans celle de la structure, donc il suffit de spécifier sizeof(*don) lors du write.

    ndh34, à partir du moment où ta structure contient au moins un pointeur, tu ne peux pas désérialiser en une ligne avec mmap(). En effet, les adresses des données peuvent changer d'une exécution à une autre (voire lors de la même exécution), il te faut donc un mécanisme un peu plus complexe pour gérer ces pointeurs.

  4. #4
    Membre Expert
    Avatar de skeud
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2011
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 1 091
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par the Hound Voir le message
    Pas sûr que ça fonctionne ... s_donnee::data est un pointeur sur char et non un tableau, son contenu ("coucou le petit lapin") n'est pas dans la structure mais alloué dans une zone mémoire à part (dans la section .rodata du binaire par exemple).
    C'est ce que j'avais dans un de mes projet pour envoyer une structure à travers le réseau.Si je ne me gourre pas, lors du write:
    le pointeur de référence (don) va etre pris puis décaler lors de l'écriture, c'est pour ça qu'il faut impérativement mettre le char* à la fin de la structure et faire un read dessus en plus de la structure pour le récupéré.
    Lorsque le write aura fini d'écrire la structure, il va passé sur le pointeur du char* et donc se décaler dans le registre pour aller à l’adresse du char* (donc dans le .rodata) puis ensuite continué le write pour écrire la chaine de caractère, c'est pour ça que ce n'est pas obligatoire de passer par un tableau de char.
    En gros:
    on prend don qui pointe sur code
    on écrit code dans le fichier
    on décale don qui va pointer sur dataSize
    on écrit dataSize dans le fichier
    on décale don qui va pointer sur valider
    on écrit valider dans le fichier
    on décale don qui va pointer sur data
    on écris data dans le fichier (on s'en fous un peu de cette valeur car elle changera complétement lors de la lecture du fichier).
    on décale don qui va pointer sur la zone mémoire pointer par data (c'est à ce moment que le pointeur va changer car on prend l'adresse suivante en fonction de l’adresse qu'on pointe actuellement, hors l’adresse qu'on pointe actuellement est celle dans le .rodata).
    on écris la zone mémoire pointer par data dans le fichier.

    Certe d'un point de vue physique, les données ne sont pas continue mais lorsque l'on utilise les pointeur, pour le programme, la mémoire est continue. Si je me souviens bien, le fonctionnement est dans ce genre .


    EDIT: meme tarif qu'au dessus, ce n'est pas du tout ce qu'il se passe, voir le message plus bas pour un code fonctionnel.

  5. #5
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2014
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

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

    Informations forums :
    Inscription : Juin 2014
    Messages : 345
    Par défaut
    Citation Envoyé par skeud Voir le message
    ...
    Non.
    write() ne fait rien d'autre qu'écrire le nombre d'octets spécifiés à l'adresse donnée dans un fichier.
    Il n'y a pas de décalage, de déréférencement de pointeur ou quoi que ce soit du genre. write() n'a aucune idée du contenu du buffer que tu lui passes. Comment la fonction pourrait-elle faire la différence quand tu lui passes une chaîne de caractère, un entier, un pointeur, ou une structure ?

    Quant à cette histoire de mémoire contiguë, ça n'a rien à voir. L'espace mémoire tel que vu par le programme (càd l'espace virtuel) est effectivement "continu", représenté sur un bloc de mémoire, mais dans ce bloc même il n'y a par défaut aucun ordre. Rien ne t'empêche d'avoir un gros bordel avec des données localisées n'importe où dans le bloc. Or c'est ici le cas, la structure et la chaîne "coucou le petit lapin" ne sont même pas dans le même segment de mémoire.
    (Aux éventuels puristes : j'ai simplifié au possible !)

  6. #6
    Membre Expert
    Avatar de skeud
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2011
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 1 091
    Billets dans le blog
    1
    Par défaut
    Effectivement je n'ai rien dis, ça ne fonctionne pas, je viens de tester, pour que cela fonctionne il faut bien écrire le buffer de donnée et non pas toute la structure d'un coup:

    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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    #include <windows.h>
    #include <iostream>
    #include <sys\types.h>
    #include <io.h>
    #include <fcntl.h>
    #include <sys\stat.h>
     
     
     
    #include <time.h> 
     
    std::string GetLastErrorStdStr(DWORD error)
    {
      if (error)
      {
        LPVOID lpMsgBuf = 0;
        DWORD bufLen = FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | 
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            error,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR) &lpMsgBuf,
            0, NULL );
        if (bufLen)
        {
          LPCSTR lpMsgStr = (LPCSTR)lpMsgBuf;
          std::string result(lpMsgStr, lpMsgStr+bufLen);
     
          LocalFree(lpMsgBuf);
     
          return result;
        }
      }
      return std::string("?????");
    }
     
    struct s_donnee
    {
      int code;
      int dataSize;
      bool variable;
      char* data;
    };
     
    int _tmain(int argc, _TCHAR* argv[])
    {
      struct s_donnee don;
      don.code = 5;
      don.variable = true;
      don.data = "coucou les petits lapin";
      don.dataSize = strlen(don.data)+1;
      int fd = open("test.txt", _O_RDWR | _O_CREAT,  _S_IREAD | _S_IWRITE );
      if (fd >= 0)
      {
        write(fd, &don, sizeof(don));
        write(fd, don.data, don.dataSize);
        close(fd);
        fd = open("test.txt", _O_RDWR);
        if (fd >= 0)
        {
          struct s_donnee ret;
          read(fd, &ret, sizeof(ret));
          ret.data = new char[ret.dataSize];
          read(fd, ret.data, ret.dataSize);
          close(fd);
          std::cout << ret.data <<std::endl;
          delete[] ret.data;
        }
        else
          std::cout << "open failed" << GetLastErrorStdStr(GetLastError()).c_str() << std::endl;
      }
      else
        std::cout << "open failed" << GetLastErrorStdStr(GetLastError()).c_str() << std::endl;
    	system("PAUSE");
    	return (0);
    }
    je vais éditer mon message pour retirer ma grosse connerie .

  7. #7
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 2
    Par défaut
    Merci pour vos réponses

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

Discussions similaires

  1. Tableau complexe avec liste d'objet sur iReport 4.7.0
    Par Mcfly3412 dans le forum iReport
    Réponses: 1
    Dernier message: 03/10/2012, 12h57
  2. Problème Serialisation Objet "complexe"
    Par l3st4t dans le forum C#
    Réponses: 3
    Dernier message: 19/10/2011, 12h24
  3. [JMX] Appel d'une méthode distante avec retour d'objet complexe
    Par hugo123 dans le forum API standards et tierces
    Réponses: 2
    Dernier message: 24/07/2009, 12h18
  4. Dessiner des objets plus complexes avec OpenGL
    Par Premium dans le forum OpenGL
    Réponses: 18
    Dernier message: 21/11/2006, 17h55
  5. Réponses: 27
    Dernier message: 03/02/2003, 12h27

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