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 :

Problème ntdll, Gestion mémoire..


Sujet :

C++

  1. #21
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 93
    Points : 63
    Points
    63
    Par défaut
    Salut jblecanard.
    Le souci c'est que lorsque je lit sur le port série :

    Cela me renvoie un char*.

    C'est pour ça que j'ai malheureusement utilisé ce type de données. Ma communication sur le port série fonctionne bien, j'aimerais si possible ne pas la modifier (là actuellement j'utilise la bibliothèque windows pour communiquer sur le port série et je prends ce qu'elle me renvoie)...
    Sinon peut-on convertir facilement du char* vers char ??

  2. #22
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Je comprend encore mieux la fuite !

    La fonction alloue elle même le résultat qu'elle t'envoie et du coup, le tableau que tu as alloué part dans les choux ! Pire, le delete risque de partir au tas aussi. Tu n'utilises pas rep et readCOM correctement. Là j'ai une réunion mais je t'explique comment faire en revenant.

    Re

    Alors on va reprendre un peu le code de la fonction concernée. Je te met mes corrections (non testées), il y a peut être de légères erreurs et je t'explique.

    Tout d'abord, le coeur du problème, le fameux rep. Ton erreur relève d'une incompréhension du fonctionnement des pointeurs. En effet, quand tu appelle readCOMDLL, celle-ci te renvoie un pointeur vers une zone mémoire qu'elle a elle même allouée. Ton pointeur ne contient plus l'adresse renvoyé par ton "new", et cette zone est donc perdue. Pour corriger cela, il ne faut pas allouer rep mais laisser la fonction le faire, et ne pas oublier de faire le ménage derrière. Par contre, on ne sait pas comment cette mémoire est allouée, c'est la documentation de la fonction qui le dira. Comme c'est une fonction C, je pense que la mémoire est allouée par malloc, et il faut donc la libérer avec free. C'est peut être une hypothèse sur laquelle il faudra revenir.

    Il faut aussi rallonger les tableaux pour accueillir le '\0'.

    J'ai transformé tes cast C-Style en casts C++.

    J'ai viré ta série de "else" inutile. Voir la technique avec le code de retour.

    Je remarque quand dans ton implémentation, derResult n'est jamais lu avant d'être écrit. Son passage en argument est donc inutile.

    Je pense également que la série de if n'est pas utile et qu'un seul appel bien senti à readCOMDLL devrait suffire.

    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
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    char* BdgCom::derQuery(char *derResult)
    {
      char * retour = NULL; // <- Tu va voir il est important pour l'élégance
     
      const size_t repSize = 7; //Taille de la trame contenant la réponse à retourner
      const size_t repInitSize = 6; //Taille de la trame contenant le début de la trame
      const size_t allRepSize = 13; //Taille de la trame contenant toute la trame
     
      const char *query = NULL;
      char *rep = NULL; //Réponse (les valeurs de débit de dose, erreur...)
      char repInit[repInitSize]; //Réponse Initial 55 AA..
      char allRep[allRepSize]; //Réponse entière pour le calcul du checksum
     
      bool isGood; //Réponse du checksum
      string trameToCheck; //Trame à vérifier (checksum)
     
      repInit[repInitSize - 1] = '\0'; // -1 très important ici et ne pas oublier que ce '\0' occupe une place !
      allRep[allRepSize - 1] = '\0'; // -1 très important ici
     
      isGood = false;
     
      // Je sais pas ce que faisais ce code mais sûrement rien d'utile. De plus sprintf c'est du C
      /* sprintf(derResult,"%s",""); //Initialisation de la variable de retour
      sprintf(rep,"%s",""); //Initialisation de la variable de retour
      sprintf(repInit,"%s",""); //Initialisation de la variable de retour
      sprintf(allRep,"%s",""); //Initialisation de la variable de retour*/
     
      //On repasse la string en const char*, création de la trame de demande :
      query = strDerQuery.c_str(); // la mémoire sera libérée par strDerQuery, on s'en préoccupe pas
     
      com.clrDTR();
      //Demande du DerQuery sur le port série :
      if(writeCOMDLL(query,sizeTrameDerQuery))
      {
        com.setDTR();
        com.purgeClearCOM();
        //---------------------------------------------------------------
        // Lecture de la réponse sur le port série :
        // Vérification du début de la trame : 55 AA 70 ...
        // On cast rep pour la comparaison avec le buffer en "unsigned char" pour aller jusqu'à 0xFF
        //---------------------------------------------------------------
        rep = readCOMDLL(1);
        if(rep && 0x55 == static_cast<unsigned char>(*rep))
        {
          repInit[0] = *rep;
          free(rep);
     
          rep = readCOMDLL(1);
          if(rep && 0xAA == static_cast<unsigned char>(*rep))  
          {
            repInit[1] = *rep;
            free(rep);
     
            rep = readCOMDLL(1);
            if(rep && 0x70 == static_cast<unsigned char>(*rep))
            {
              repInit[2] = *rep;
              free(rep);
     
              rep = readCOMDLL(1);
              if(rep && 0xFF > static_cast<unsigned char>(*rep))
              {
                repInit[3] = *rep;
                free(rep);
     
                rep = readCOMDLL(1);
                if(rep && 0x01 == static_cast<unsigned char>(*rep) )
                {
                  repInit[4] = *rep;
                  free(rep);
     
                  rep = readCOMDLL(repSize);
                  if(rep)
                  {
                    //-----------------------
                    //Calcul du checksum
                    //-----------------------
                    sprintf(allRep,"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
                      (unsigned char)repInit[0],(unsigned char)repInit[1],
                      (unsigned char)repInit[2],(unsigned char)repInit[3],(unsigned char)repInit[4],
                      (unsigned char)rep[0],(unsigned char)rep[1],
                      (unsigned char)rep[2],(unsigned char)rep[3],(unsigned char)rep[4],
                      (unsigned char)rep[5],(unsigned char)rep[6]);
                    trameToCheck.assign(allRep);
                    try
                    {
                      cout << "Trame avant checksum --> "; //DEBUG
                      cout << allRep << endl; //DEBUG
                      isGood = checksumdDLL(trameToCheck);
                    }
                    catch (const std::exception &e)
                    {
                      cout << "ERROR CHECKSUM " << endl;
                      cerr << e.what();
                      //return (0);
                    }
                    sprintf(retour,"%c%c%c",rep[0],rep[4],'\0');
     
                    free(rep);
                    rep = NULL;
                  }
                }
              }
            }
          }
        }
        com.clrDTR();
      }
     
      return retour;
    }
    Je n'ai pas testé le code mais je t'ai donné les clés pour le corriger (normalement). Bon courage et n'hésite pas à poser des questions (j'ai pas le temps de détailler plus mais je pourrais le faire plus tard).

  3. #23
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 93
    Points : 63
    Points
    63
    Par défaut
    Merci pour cette réponse très constructive, j'ai un peu mieux compris certaine zone obscur du monde des pointeurs..
    Ça bug sur le free(), la mémoire ne doit pas être alloué comme tu l'as dit.
    J'ai peut être fait n'importe quoi,lorsque je lis sur le port série je fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return com.readCOM(&chaineRecue, nbCharRx);
    où chaine reçu est une variable de classe de la classe BdgCom...

    En tout cas merci !

  4. #24
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Hum d'accord je regarderais ça dès que j'ai l'occaze, là c'est le week end, tu devrais y aller aussi

  5. #25
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 93
    Points : 63
    Points
    63
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    Hum d'accord je regarderais ça dès que j'ai l'occaze, là c'est le week end, tu devrais y aller aussi
    Merci et bon week end !

  6. #26
    Membre confirmé
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Points : 641
    Points
    641
    Par défaut
    Dans ton code d'origine :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
                rep = NULL;
                delete[] rep;
    Tu mettais le pointeur à NULL avant le delete !

    La tu delete un pointeur null mais surement pas le bloc à liberer.

  7. #27
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Essaye de faire tourner le bousin sans les free. Ca fera peut être une fuite de mémoire, mais au moins tu verras si ça plante ou pas.

    Citation Envoyé par krapo13 Voir le message
    J'ai peut être fait n'importe quoi,lorsque je lis sur le port série je fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return com.readCOM(&chaineRecue, nbCharRx);
    où chaine reçu est une variable de classe de la classe BdgCom...
    Pour t'aider sur ce point, il faudrait nous montrer le header SerialPort.h, éventuellement le code mais je suppose que tu ne l'as pas et que tu linkes sur une librairie.

    Citation Envoyé par Lucien63 Voir le message
    Dans ton code d'origine :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
                rep = NULL;
                delete[] rep;
    Tu mettais le pointeur à NULL avant le delete !
    Exact très grosse erreur mais qui provoque une fuite de mémoire et pas un crash normalement.

  8. #28
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 93
    Points : 63
    Points
    63
    Par défaut
    Salut !
    Alors ça y'est, je n'ai plus de problèmes de crash même en release...
    Je me suis inspiré de ce jblecanard à fait... Au début j'avais toujours les crash ntdll je me suis inspiré de la variable query en créant une variable strRep de type string et en mettant la variable rep en const char * et en faisant :
    Si j'ai bien compris, lorsqu'on va sortir de la méthode, rep sera supprimé...
    Du moment que j'ai fait ça plus de souci, même avec le calcul du checksum...

    Le code :

    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
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
     
    char* BdgCom::derQuery(char *derResult)
    {
        const size_t repSize = 8; //Taille de la trame contenant la réponse à retourner
        const size_t repInitSize = 6; //Taille de la trame contenant le début de la trame
        const size_t allRepSize = 13; //Taille de la trame contenant toute la trame
     
        char* retour = NULL; // <- Tu va voir il est important pour l'élégance
        retour = new char(allRepSize);
        const char* query = NULL;
        const char *rep = NULL; //Réponse (les valeurs de débit de dose, erreur...)
        char repInit[repInitSize]; //Réponse Initial 55 AA..
        char allRep[allRepSize]; //Réponse entière pour le calcul du checksum
     
        bool isGood; //Réponse du checksum
        string trameToCheck; //Trame à vérifier (checksum)
        string strRep;
     
        trameToCheck.assign("");
        strRep.assign("");
     
        repInit[repInitSize - 1] = '\0'; // -1 très important ici et ne pas oublier que ce '\0' occupe une place !
        allRep[allRepSize - 1] = '\0'; // -1 très important ici
     
        isGood = false;
     
        //On repasse la string en const char*, création de la trame de demande :
        query = strDerQuery.c_str(); // la mémoire sera libérée par strDerQuery, on s'en préoccupe pas
        rep = strRep.c_str();
     
        com.clrDTR();
        //Demande du DerQuery sur le port série :
        if(writeCOMDLL(query,sizeTrameDerQuery))
        {
            com.setDTR();
            com.purgeClearCOM();
            //---------------------------------------------------------------
            // Lecture de la réponse sur le port série :
            // Vérification du début de la trame : 55 AA 70 ...
            // On cast rep pour la comparaison avec le buffer en "unsigned char" pour aller jusqu'à 0xFF
            //---------------------------------------------------------------
            rep = readCOMDLL(1);
            if(rep && 0x55 == static_cast<unsigned char>(*rep))
            {
                repInit[0] = *rep;
                rep = NULL;
                delete[] rep;
     
                rep = readCOMDLL(1);
                if(rep && 0xAA == static_cast<unsigned char>(*rep))
                {
                    repInit[1] = *rep;
                    rep = NULL;
                    delete[] rep;
     
                    rep = readCOMDLL(1);
                    if(rep && 0x70 == static_cast<unsigned char>(*rep))
                    {
                        repInit[2] = *rep;
                        rep = NULL;
                        delete[] rep;
     
                        rep = readCOMDLL(1);
                        if(rep && 0xFF > static_cast<unsigned char>(*rep))
                        {
                            repInit[3] = *rep;
                            rep = NULL;
                            delete[] rep;
     
                            rep = readCOMDLL(1);
                            if(rep && 0x01 == static_cast<unsigned char>(*rep) )
                            {
                                repInit[4] = *rep;
                                rep = NULL;
                                delete[] rep;
     
                                rep = readCOMDLL(repSize - 1);
     
                                if(rep)
                                {
                                    //-----------------------
                                    //Calcul du checksum
                                    //-----------------------
     
                                    sprintf(retour,"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
                                    (unsigned char)repInit[0],(unsigned char)repInit[1],
                                    (unsigned char)repInit[2],(unsigned char)repInit[3],(unsigned char)repInit[4],
                                    (unsigned char)rep[0],(unsigned char)rep[1],
                                    (unsigned char)rep[2],(unsigned char)rep[3],(unsigned char)rep[4],
                                    (unsigned char)rep[5],(unsigned char)rep[6]);
     
                                    trameToCheck.assign(retour);
                                    try
                                    {
                                        cout << "Trame avant checksum --> "; //DEBUG
                                        cout << retour << endl; //DEBUG
                                        isGood = checksumdDLL(trameToCheck);
                                    }
                                    catch (const std::exception &e)
                                    {
                                        cout << "ERROR CHECKSUM " << endl;
                                        cerr << e.what();
                                    }
     
                                    sprintf(retour,"%02X%c%02X%c",(unsigned char)rep[0],'_',(unsigned char)rep[4],'\0');
                                    cout << "DED dans BDgCom --> "; //DEBUG
                                    cout << retour << endl; //DEBUG
                                    rep = NULL;
                                    delete[] rep;
                                }
                            }
                        }
                    }
                }
            }
        }
        if(rep != NULL)
        {
            rep = NULL;
            delete[] rep;
        }
        com.clrDTR();
        return retour;
    }
    J'ai la classe SerialPort, je l'ai trouvé sur un autre site et je l'ai un peu adapté.
    Sinon j'ai oublié de dire, j'ai toujours une petite fuite mémoire, mais ça viens surement d'un autre endroit du code... En tout cas cela ne crash plus !

    le .h :

    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
     
    #ifndef SerialPort_H
    #define SerialPort_H
     
    #include <windows.h>
    #include <iostream>
    #include <stdio.h>
     
    class SerialPort
    {
        public:
            SerialPort();
            SerialPort(DWORD rx, DWORD tx, int sizeRxMax, int sizeTxMax);
            virtual ~SerialPort();
     
            bool connectCOM(const char *port,const char *parite,int vitesse,int data,const char *stopBit,int timeOut);
            bool closeCOM();
            bool writeCOM(const char *chaine,int nbCharTx=0); //Chaine à envoyer + taille de la chaine
            char* readCOM(char *chaineRecue, int nbCharRx=0);
            bool purgeClearCOM();
            bool purgeAbortCOM();
            bool purgeAllCOM();
            bool clrDTR();
            bool setDTR();
     
        private:
            DCB dcb;						// déclarer une variable contenant la configuration du port
            HANDLE hCom;					// déclarer un handle
            COMMTIMEOUTS tTimeout;          //Temps de latence
            bool fWaitingOnRead;
            DWORD rxBuffer;                 //Taille du buffer d'entrée en octets
            DWORD txBuffer;                 //Taille du buffer de sortie en octets
            int sizeMsgRx;                  //Taille du message à recevoir en nb de caractères
            int sizeMsgTx;                  //Taille du message à envoyer en nb de caractères
    };
     
    #endif // SerialPort_H
    le .cpp :

    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
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
     
    #include "SerialPort.h"
     
    using namespace std;
     
    /*------------------------------------------------------------------------
    *                 CONSTRUCTEURS ET DESTRUCTEUR DE LA CLASSE
    * Parametres
    * DWORD rx		    : Taille du buffer de reception
    * DWORD tx          : Taille du buffer d'emission
    * int sizeRx        : Nombre de caractères du message de reception
    * int sizeTx        : Nombre de caractères du message d'emission
    *------------------------------------------------------------------------	*/
    SerialPort::SerialPort()
    {
        fWaitingOnRead = false;
        rxBuffer = 4096;
        txBuffer = 4096;
        sizeMsgRx = 4096;
        sizeMsgTx = 4096;
        //MessageBox(NULL,"BONJOUR","SERIAL",MB_OK|MB_ICONEXCLAMATION);
    }
     
    SerialPort::SerialPort(DWORD rx, DWORD tx, int sizeRxMax, int sizeTxMax)
    {
        fWaitingOnRead = false;
        rxBuffer = rx;
        txBuffer = tx;
        sizeMsgRx = sizeRxMax;
        sizeMsgTx = sizeTxMax;
        //MessageBox(NULL,"BONJOUR","SERIAL",MB_OK|MB_ICONEXCLAMATION); //DEBUG
    }
     
    SerialPort::~SerialPort()
    {
        if(hCom!=NULL)
        {
            //MessageBox(NULL,"AU REVOIR, hcom not null","SERIAL",MB_OK|MB_ICONEXCLAMATION); //DEBUG
            purgeAllCOM();
            closeCOM();
        }
        //MessageBox(NULL,"AU REVOIR hcom null","SERIAL",MB_OK|MB_ICONEXCLAMATION); //DEBUG
    }
     
     
    /*------------------------------------------------------------------------
    *                 Fonction d'ouverture du port SerialPort
    *
    * Parametres
    * char *port		: "COM1" pour Port1, "COM2" pour port2
    * parite            : "Aucune", "Paire", "Impaire"
    * vitesse           : 9600, 19200..
    * data              : data bit 8...
    * stopBit           : 1, 1.5  ou 2
    * timeOut           : Temps avant d'arrêter le process de communication au bout de x (ms)
    *
    * Retour : un boolean egal à 0 si erreur.
    *------------------------------------------------------------------------	*/
    bool SerialPort::connectCOM(const char *port,const char *parite,int vitesse,int data,const char *stopBit,int timeOut)
    {
        cout << "Ouverture port (serial) : " << endl; //DEBUG
        DWORD dwError;					// n° de l’erreur
    	bool fSuccess;					// tout c’est bien passé
     
    	/*--------------------------------------------------------*/
    	/*                 Ouverture du port de Com               */
    	/*--------------------------------------------------------*/
    	hCom = CreateFile(
    		port,                         	// Choix du port « COMx »
    		GENERIC_READ | GENERIC_WRITE, 	// accès pour lire et écrire sur le port
    		0,                            	// accès exclusif au port de COM
    		NULL,                         	// sécurité par défaut
    		OPEN_EXISTING,                	//Doit être à cette valeur car se n’est pas un fichier
    		0,			                    //FILE_FLAG_OVERLAPPED,
    		NULL);							// mode synchrone
     
    	/*-----------------------------------------------------------*/
    	/*         Vérifier si handle ouvert correctement            */
    	/*-----------------------------------------------------------*/
    	if (hCom == INVALID_HANDLE_VALUE)
        {
            dwError = GetLastError();
            MessageBox(NULL,"Erreur lors de l'ouverture du port","ERREUR",MB_OK|MB_ICONEXCLAMATION);
            closeCOM();
        }
     
    	/*-----------------------------------------------------------*/
    	/* Lecture Configuration initiale                            */
    	/*-----------------------------------------------------------*/
    	fSuccess = GetCommState(hCom, &dcb);
     
    	if (!fSuccess)
        {
            MessageBox(NULL,"Erreur lors de la configuration du port","ERREUR",MB_OK|MB_ICONEXCLAMATION);
    		closeCOM();
        }
     
    	/*-------------------------------------------------------------------*/
    	/* 					Configuration du port                            */
    	/*-------------------------------------------------------------------*/
    	// Gestion de la vitesse
    	dcb.BaudRate = vitesse;
     
    	// Gestion du nombre de bits
    	dcb.ByteSize = data;
     
    	// Gestion de la parité
    	if (strcmp(parite,"Aucune")==0)
    		dcb.Parity = NOPARITY;
     
    	if (strcmp(parite,"Paire")==0)
    		dcb.Parity = EVENPARITY;
     
    	if (strcmp(parite,"Impaire")==0)
    		dcb.Parity = ODDPARITY;
     
    	//Gestion du Stop Bit
    	if (strcmp(stopBit,"2")==0)
    		dcb.StopBits = TWOSTOPBITS;
     
    	else if (strcmp(stopBit,"1.5")==0)
    		dcb.StopBits = ONE5STOPBITS;
     
    	else
    		dcb.StopBits = ONESTOPBIT;
     
        dcb.fParity=TRUE;
        dcb.fBinary=TRUE; //Autoriser le binaire et pas seulement l'ascii, no EOF check
        dcb.fNull=FALSE; //Autoriser l'octet 0x00
        dcb.fErrorChar=FALSE;
        dcb.fAbortOnError=FALSE; // 1 --> Arrêt si erreur
        dcb.fInX=FALSE;
        dcb.fOutX=FALSE;
        dcb.fOutxCtsFlow=FALSE;
        dcb.fOutxDsrFlow=FALSE;
        dcb.fDsrSensitivity=FALSE;
        dcb.fTXContinueOnXoff=TRUE;
        dcb.fRtsControl=RTS_CONTROL_ENABLE;
        dcb.fDtrControl=DTR_CONTROL_ENABLE;
     
    	 /*----------------------------------*/
    	 /*    Définition des timeouts       */
    	 /*----------------------------------*/
    	tTimeout.ReadIntervalTimeout = 20; //Temps en ms en entrée entre 2 caractères
    	tTimeout.ReadTotalTimeoutMultiplier = 0;
    	tTimeout.ReadTotalTimeoutConstant = timeOut; // pas de time out = 0
    	tTimeout.WriteTotalTimeoutMultiplier = 0;
    	tTimeout.WriteTotalTimeoutConstant = 0;
     
    	// affectation taille des tampons d'émission et de réception
        SetupComm(hCom,rxBuffer,txBuffer);
     
    	/*-----------------------------------------------*/
    	/* Configurer le port	                          */
    	/*-----------------------------------------------*/
    	/* configuration du port COM */
        if(!SetCommTimeouts(hCom, &tTimeout) || !SetCommState(hCom, &dcb))
        {
            MessageBox(NULL,"Erreur lors de la configuration du port","ERREUR",MB_OK|MB_ICONEXCLAMATION);
            closeCOM();
            return false;
        }else
        {
            fSuccess = true;
        }
     
    	if(fSuccess)
    	{
            /* on vide les tampons d'émission et de réception, mise à 1 DTR */
            purgeAllCOM();
            setDTR();
            return fSuccess;
    	}else{
            MessageBox(NULL,"Erreur lors de la configuration du port","ERREUR",MB_OK|MB_ICONEXCLAMATION);
            closeCOM();
            return false;
    	}
    }
     
    /*------------------------------------------------------------------------
    *                 Fonction de fermeture du port SerialPort
    *
    * Retour : un boolean egal à 0 si erreur.
    *------------------------------------------------------------------------	*/
    bool SerialPort::closeCOM()
    {
        cout << "Fermeture port (serial) : " << endl; //DEBUG
        /* fermeture du port COM */
        if(hCom!=NULL)
        {
            CloseHandle(hCom);
        }
        return true;
    }
     
    /*------------------------------------------------------------------------
    *                 Fonction d’écriture sur un port SerialPort
    *
    * Parametres
    *  char *chaine	:chaine à envoyer sur le port
    *  int nbCharTx	:longueur de la tame envoyé en octet (par défaut 0)
    *
    * Retour : un entier egal à 0 si erreur.
    *------------------------------------------------------------------------	*/
    bool SerialPort::writeCOM(const char *chaine, int nbCharTx)
    {
    	BOOL fSuccess = false;
    	unsigned long nBytesWrite;
     
    	//Cas ou nbCharTx n'est pas renseigné :
    	if(nbCharTx==0)
    	{
    	    nbCharTx = sizeof(chaine);
    	}
     
    	// écrire dans le fichier
    	fSuccess = WriteFile(hCom,chaine,nbCharTx,&nBytesWrite,NULL);
     
    	return fSuccess;
    }
     
    /*-----------------------------------------------------------------------
    * 					Fonction de lecture sur le port série
    *
    * Parametres
    * char *chaineRecue	: chaine recu sur le port
    *
    * Retour : une chaine de caractères
    * ----------------------------------------------------------------------*/
    char* SerialPort::readCOM(char *chaineRecue, int nbCharRx)
    {
    	BOOL fSuccess = false;
    	BOOL bResult = false;
    	unsigned long nBytesRead;
    	char *inBuffer;
     
    	//Cas ou nbCharRx n'est pas renseigné :
    	if(nbCharRx<1)
    	{
    	    nbCharRx = sizeMsgRx;
    	}
     
    	/*-------------------------------------*/
    	/* Initialisation des variables        */
    	/*-------------------------------------*/
    	inBuffer = NULL;
    	inBuffer  = new char[nbCharRx+1]; // réservation mémoire pour le buffer de réception
    	sprintf(inBuffer,"%s","");
    	nBytesRead=0;
     
    	/*-------------------------------------------------------------*/
    	/* boucle d'attente de lecture des octets                      */
    	/* Sortie de la boucle par timeout par exemple, si             */
    	/* l’on suppose le format de la trame reçu est               */
    	/* variable.                                                   */
    	/*-------------------------------------------------------------*/
        if(!fWaitingOnRead)
        {
            bResult = ReadFile(hCom,inBuffer,nbCharRx,&nBytesRead,NULL);
            if(!bResult)
            {
                if (GetLastError() != ERROR_IO_PENDING)     // read not delayed?
                    MessageBox(NULL,"Erreur lors de la lecture du buffer...","ERREUR",MB_OK|MB_ICONEXCLAMATION); //DEBUG
                else
                    fWaitingOnRead = true;
            }
            fSuccess = true;
        }
    	inBuffer[nBytesRead] = '\0';
     
        //sprintf(chaineRecue,"%s",inBuffer);
        // Copie du buffer dans la variable de retour
        for(int i=0; i<=nbCharRx; i++)
        {
            chaineRecue[i] = inBuffer[i];
        }
     
    	// Libérer la mémoire
    	inBuffer = NULL;
    	delete[] inBuffer;
     
    	return chaineRecue;
    }
     
     
    /*-----------------------------------------------------------------------
    * 					Fonction de puge du port série (rxclear et txclear)
    *
    * Efface le tampon d'entrée et sortie
    *
    *
    * Retour : un entier egal à 0 si erreur.
    * ----------------------------------------------------------------------*/
    bool SerialPort::purgeClearCOM()
    {
        bool purge = false;
     
        if(hCom==NULL)
        {
            return false;
        }
        // flush the port
        purge = PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR);
        return purge;
    }
     
    /*-----------------------------------------------------------------------
    * 					Fonction de puge du port série (rxabort et txabort)
    *
    * Termine toutes les opérations de lecture/écriture en circulation
    * même si les opérations de lecture/écriture n'ont pas été achevées.
    *
    *
    * Retour : un entier egal à 0 si erreur.
    * ----------------------------------------------------------------------*/
    bool SerialPort::purgeAbortCOM()
    {
        bool purge = false;
     
        if(hCom==NULL)
        {
            return false;
        }
        // flush the port
        purge = PurgeComm(hCom, PURGE_RXABORT | PURGE_TXABORT);
        return purge;
    }
     
    /*-----------------------------------------------------------------------
    * 					Fonction de puge du port série
    *
    * Efface le tampon et termine les opérations de lecture/écriture
    *
    * Retour : un entier egal à 0 si erreur.
    * ----------------------------------------------------------------------*/
    bool SerialPort::purgeAllCOM()
    {
        bool purge = false;
     
        if(hCom==NULL)
        {
            return false;
        }
        // flush the port
        purge = PurgeComm(hCom, PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR);
        return purge;
    }
     
    /*-----------------------------------------------------------------------
    * 					Fonction de d'effacememt du DTR(Data Terminal Ready)
    *
    *
    * Retour : un entier egal à 0 si erreur.
    * ----------------------------------------------------------------------*/
    bool SerialPort::clrDTR()
    {
        bool clr = false;
     
        if(hCom==NULL)
        {
            return false;
        }
        clr = EscapeCommFunction(hCom,CLRDTR);
        return clr;
    }
     
    /*-----------------------------------------------------------------------
    * 					Fonction de d'envoie du DTR(Data Terminal Ready)
    *
    *
    * Retour : un entier egal à 0 si erreur.
    * ----------------------------------------------------------------------*/
    bool SerialPort::setDTR()
    {
        bool set = false;
     
        if(hCom==NULL)
        {
            return false;
        }
        set = EscapeCommFunction(hCom,SETDTR);
        return set;
    }

  9. #29
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Hello !

    Alors là... ça ne va pas du tout J'ai compris pourquoi ça marche et c'est du hasard et de la chance. Ton code n'est pas écrit correctement.

    Tout d'abord, tu fais dans SerialPort::readCOM l'erreur soulevée par Lucien. Tu met le pointeur à NULL avant le delete. C'est très mal, ça ne peut pas fonctionner ! Si ton pointeur est NULL, delete ne peut pas savoir où il doit effacer la mémoire, puisque ton pointeur ne contient plus aucune information exploitable. Il faut corriger celà, ça provoque des fuites de mémoire.

    Ensuite, ta manière d'allouer rep ne convient pas. Je pense que tu connais mal le mécanisme d'allocation/destruction et c'est ce qui provoque des problèmes. Lorsque tu utilises le const char * renvoyé par std::string::c_str(), il doit pas être utilisé pour l'écriture, et c'est la raison pour laquelle il est const. Cela te donne accès à un tableau de char utilisé par la chaîne, mais il ne faut en aucun cas le manipuler. En revanche, tu peux l'utiliser en lecture si tu en as besoin, et tu n'as pas de delete à faire, car le delete de cette zone mémoire est encapsulé dans le destructeur de la std::string qui le possède.

    Maintenant que j'ai le code de SerialPort, je comprend mieux ce qu'il se passe. Voici une proposition de code corrigé. Je remarque notamment que :
    - Le char * de retour de readCOM est strictement inutile.
    - La méthode readCOMDLL est inutile et au contraire source d'erreurs

    Honnêtement, ton code mériterait d'être réécris entièrement , mais bon je vais pas tout te réécrire parce que ce serait long pour moi et surtout pas pédagogique. Je t'ai passé les manipulations de chaînes en C++ (tu faisais du C). Le format obtenu dans output n'est peut être pas le bon (je connais pas sprintf car c'est du C ça me sers jamais). Si c'est le cas, on peut l'arranger, encore et toujours en C++.

    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
    79
    80
    81
    82
    83
    84
    85
    std::string BdgCom::derQuery(char *derResult)
    {
      const size_t repSize = 8; //Taille de la trame contenant la réponse à retourner
      const size_t repInitSize = 6; //Taille de la trame contenant le début de la trame
     
      std::string resultat; // <- Tu va voir il est important pour l'élégance
     
      const char* query = NULL;
      const char rep[repSize]; //Réponse (les valeurs de débit de dose, erreur...)
      char repInit[repInitSize]; //Réponse Initial 55 AA..
     
      bool isGood; //Réponse du checksum
      string trameToCheck; //Trame à vérifier (checksum)
     
      rep[repSize - 1] = '\0';
      repInit[repInitSize - 1] = '\0'; // -1 très important ici et ne pas oublier que ce '\0' occupe une place !
     
     
      isGood = false;
     
      //On repasse la string en const char*, création de la trame de demande :
      query = strDerQuery.c_str(); // la mémoire sera libérée par strDerQuery, on s'en préoccupe pas
      rep = strRep.c_str();
     
      com.clrDTR();
      //Demande du DerQuery sur le port série :
      if(writeCOMDLL(query,sizeTrameDerQuery))
      {
        com.setDTR();
        com.purgeClearCOM();
        //---------------------------------------------------------------
        // Lecture de la réponse sur le port série :
        // Vérification du début de la trame : 55 AA 70 ...
        // On cast rep pour la comparaison avec le buffer en "unsigned char" pour aller jusqu'à 0xFF
        //---------------------------------------------------------------
        com.readCOM(rep,5);
     
        if(0x55 == static_cast<unsigned char>(rep[0])
          && 0xAA == static_cast<unsigned char>(rep[1])
          && 0x70 == static_cast<unsigned char>(rep[2])
          && 0xFF > static_cast<unsigned char>(rep[3])
          && 0x01 == static_cast<unsigned char>(rep[4])
          )
        {
     
          for(size_t i = 0; i < 5; i++)
            repInit[i] = rep[i];
     
          com.readCOM(repSize - 1);
          if(rep)
          {
            //-----------------------
            //Calcul du checksum
            //-----------------------
            std::ostringstream output;
     
            for(size_t i = 0; i < 5; i++)
              output << std::hex << static_cast<unsigned char>(repInit[i]);
     
            for(size_t i = 0; i < repSize - 1; i++)
              output << std::hex << static_cast<unsigned char>(rep[i]);
     
            trameToCheck = output.str();
            try
            {
              cout << "Trame avant checksum --> "; //DEBUG
              cout << trameToCheck << endl; //DEBUG
              isGood = checksumdDLL(trameToCheck);
            }
            catch (const std::exception &e)
            {
              cout << "ERROR CHECKSUM " << endl;
              cerr << e.what();
            }
     
            output << std::hex << static_cast<unsigned char>rep[0] << "_" << std::hex << static_cast<unsigned char>(rep[4]);
            resultat = output.str();
            cout << "DED dans BDgCom --> "; //DEBUG
            cout << retour << endl; //DEBUG
          }
        }
      }
      com.clrDTR();
      return retour;
    }

  10. #30
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 93
    Points : 63
    Points
    63
    Par défaut
    Merci jblecanard pour toute cette aide...
    C'est vrai que je connais mal le mécanisme d'allocation/destruction et C / C++ en général. Je n'avais jamais fait de C ni de C++ avant ce programme là. Pour l'instant je codais en Java, Php et Vb.. Mais quand on m'a demandé de crée un DLL je me suis mis au C++.
    Bon en tout cas c'est cool, j'ai l'impression d'en apprendre à chaque message.
    Deux petits points que je ne comprends pas :

    - Pourquoi avoir mis rep en const char ? (de plus j'ai une erreur à la compilation, pb d'initialisation ), et d'autre part readCOM attend un char *(Dois je le remplacer par un autre type ?)

    - C'est vrai que j'utilisais sprintf
    que j'avais trouvé sur le site www.cplusplus.com, mais ostringstream à l'air vraiment très bien par contre je n'arrive pas à l'utiliser pour avoir ce que je veux.. En gros je veux la valeur héxadécimal du caractère en entrée mais sous la forme de chaine.. le caractère 'U' doit me donner la chaine "55"...

    Merci

  11. #31
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Hello

    C'est une erreur de ma part, il faut enlever la qualification const et surtout enlever la ligne :

    Ensuite, pour le format, facile. Il faut utiliser std::hex et les caster en unsigned int et pas en unsigned char. Comme dans cet exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main(int argc, char* argv[])
    {
      std::ostringstream resultat;
      char monChar = 0x55;
      resultat << std::hex << static_cast<unsigned int>(monChar);
      std::cout << resultat.str() << std::endl;
      return 0;
    }
    D'une manière générale, je pense que tu devrais t'acheter un bon bouquin sur C++. Et surtout n'hésite pas à user et abuser de la FAQ du site. Va même y faire un tour comme ça pour voir, je suis sûr que tu apprendras des tas de choses.

    PS : Méfie toi de cppfrance, les codes sources qu'on y trouve sont souvent de mauvaise qualité.

  12. #32
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 93
    Points : 63
    Points
    63
    Par défaut
    J'avais enlever la ligne :

    Par contre pour la conversion il y a quelques soucis puisqu’elle est dans une boucle. Avec par exemple ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    std::ostringstream resultat;
        char monChar = 0x55;
        resultat << std::hex << static_cast<unsigned int>(monChar);
        std::cout << resultat.str() << std::endl;
        monChar = 0xAA;
        resultat << std::hex << static_cast<unsigned int>(monChar);
        std::cout << resultat.str() << std::endl;
        monChar = 0x01;
        resultat << std::hex << static_cast<unsigned int>(monChar);
        std::cout << resultat.str() << std::endl;
    Première ligne j'ai bien "55".
    Puis ensuite ça se concatène
    Deuxième ligne --> "55ffffffaa"

    Lorsque que monChar vaut par exemple 0x01, j'ai 1 en sortie alors que je voudrais 01...
    Que faut-il faire ?

  13. #33
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Voilà la technique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <iostream>
    #include <sstream>
    #include <iomanip>
     
    int main(int argc, char* argv[])
    {
      std::ostringstream resultat;
      char monChar = 0x01;
      resultat << std::hex << std::setw(2) << std::setfill('0') << static_cast<unsigned int>(monChar);
      std::cout << resultat.str() << std::endl;
      return 0;
    }

  14. #34
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 93
    Points : 63
    Points
    63
    Par défaut
    Merci jblecanard !!!

    Je crois que je vais bientôt pouvoir mettre résolu, je vais nettoyer un peu le code avec tout ce que tu m'as appris et faire encore quelques tests... En tout cas je n'ai plus de fuite mémoire !

  15. #35
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Et voilà une petite astuce pour rendre le code plus sympa :

    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
    #include <iostream>
    #include <sstream>
    #include <iomanip>
     
    inline std::ostream& __CLRCALL_OR_CDECL monFormat(std::ostream& _Iosbase)
    {
      _Iosbase.setf(std::ios_base::hex, std::ios_base::basefield);
      _Iosbase.width(2);
      _Iosbase.fill('0');
      return (_Iosbase);
    }
     
    int main(int argc, char* argv[])
    {
      std::ostringstream resultat;  
      char monChar = 0x01;
      char monChar2 = 0x02;
      char monChar3 = 0x03;
     
      resultat 
        << monFormat << static_cast<unsigned int>(monChar)
        << monFormat << static_cast<unsigned int>(monChar2)
        << monFormat << static_cast<unsigned int>(monChar3);
     
      std::cout << resultat.str() << std::endl;
      return 0;
    }

  16. #36
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 93
    Points : 63
    Points
    63
    Par défaut
    Salut,

    Tout à l'air de bien fonctionner et j'apprends à utiliser les flux qui sont très utiles (http://cpp.developpez.com/faq/cpp/?page=SL) ...
    J'ai cependant toujours le même souci avec ostringstream...

    Avec cet exemple, il y a des "ff" qui s'ajoutent :

    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
     
    using namespace std;
     
    int main()
    {
        std::ostringstream resultat1, resultat2, resultat3;
        char monChar = 0x55;
        resultat1 << hex << setw(2) << setfill('0') << uppercase << static_cast<unsigned int>(monChar);
        std::cout << resultat1.str() << std::endl;
        monChar = 0xAA;
        resultat2 << hex << setw(2) << setfill('0') << uppercase <<  static_cast<unsigned int>(monChar);
        std::cout << resultat2.str() << std::endl;
        monChar = 0x01;
        resultat3 << hex << setw(2) << setfill('0') << uppercase <<  static_cast<unsigned int>(monChar);
        std::cout << resultat3.str() << std::endl;
        return 0;
    }
    Si je ne me trompe pas ça vient du cast en int qui est sur 4 octets...
    Comment faire ?

  17. #37
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Hello

    Hum en fait le casting d'un char vers un int place tout les bits manquants à 1 et pas à zéro.

    Tu peux t'en sortir comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
      int mask = 0x000000ff;
      std::ostringstream resultat2;  
      resultat2 << std::uppercase << std::hex << std::setw(2) << std::setfill('0') <<  (static_cast<int>(monChar) & mask);
      std::cout << resultat2.str() << std::endl;
    Ca marche. Je cherche une autre solution mais j'ai pas trouvé pour le moment. Version factorisée :

    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
    #include <iostream>
    #include <sstream>
    #include <iomanip>
     
    inline std::ostream& __CLRCALL_OR_CDECL monFormat(std::ostream& _Iosbase)
    {
      _Iosbase.setf(std::ios_base::hex, std::ios_base::basefield);
      _Iosbase.width(2);
      _Iosbase.fill('0');
      _Iosbase.setf(std::ios_base::uppercase);
      return (_Iosbase);
    }
     
    inline int getHexaDecimalChar(char iChar)
    {
      int mask = 0x000000ff;
      return (static_cast<int>(iChar) & mask);
    }
     
     
    int main(int argc, char* argv[])
    {
      char monChar = 0xAA;
      std::ostringstream resultat;  
      resultat << monFormat << getHexaDecimalChar(monChar);
      std::cout << resultat.str() << std::endl;
     
      return 0;
    }

  18. #38
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    93
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 93
    Points : 63
    Points
    63
    Par défaut
    Résolu, merci à tous ...

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Problème de gestion de mémoire - grosses matrices
    Par julesu dans le forum Fortran
    Réponses: 9
    Dernier message: 26/05/2008, 11h04
  2. Problème de gestion de mémoire
    Par Baud10 dans le forum MFC
    Réponses: 6
    Dernier message: 04/01/2008, 10h49
  3. Problème de gestion de mémoire (segfault)
    Par Michaël dans le forum C
    Réponses: 7
    Dernier message: 26/05/2007, 09h30
  4. Problème de gestion de la mémoire
    Par johnbob789 dans le forum Langage
    Réponses: 6
    Dernier message: 28/11/2006, 20h24
  5. [C# 2.0] Problème gestion mémoire
    Par Stéphane-M dans le forum Windows Forms
    Réponses: 13
    Dernier message: 21/09/2006, 14h36

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