[center]Bonjour,[/center]
je suis amené ces temps-ci à relire des fichiers binaires enregistrés au format big-endian, ma distribution F14 tournant sur une plateforme Intel, donc little-endian, j'utilise Ghex pour m'aider à déboguer mon programme, mais comme vous allez le constater, j'ai rencontré quelques problèmes
à titre d'information, la version de ghex utilisée correspond au rpm suivant : ghex-2.24.0-5.fc13.x86_64
les données binaires à relire sont enregistrées dans des fichiers générés par LabVIEW, et contiennent des données au format cluster (un équivalent du struct C/C++), avec dans ce cluster, un tableau de nombres réels au format double (donc codé sur 64 bits)
à l'aide de LabVIEW, j'ai regénéré le fichier, à l'origine au format big-endian, pour l'enregistrer au format little-endian
dans ce format little-endian, voilà ce que Ghex me donne (voir première image ci-dessous)

la lecture se passe bien quant on relit le fichier au format little-endian, mais ça déraille quand on prend le fichier contenant les mêmes données, mais au format big-endian ; en effet, au lieu de 1535.383, on obtient 2,895473e-287 (voir image ci-dessous, avec l'option little-endian désactivée puisque les données contenues dans le fichier sont au format big-endian)
au format big-endian (et je l'ai vérifié par ailleurs avec un petit bout de programme C++, voir plus bas), le nombre signifie pourtant bien 1535.383
lecture erronée du nombre au format flottant 64 bits _type C double_ enregistré au format big-endian

Ghex m'a induit en erreur pendant pas mal de temps, c'est alors que j'ai remarqué qu'un décalage de 4 octets vers la gauche du pointeur de lecture de Ghex permettait alors d'afficher les nombres (situés en réalité 4 octets plus loin) au format flottant 64 bits de façon correcte
lecture "correcte" du nombre au format flottant 64 bits _type C double_ enregistré au format big-endian, seulement si un décalage de 4 octets à gauche est effectué

là aussi, si un décalage de 4 octets est effectué sur les 99 nombres flottants 64 bits suivants, on parvient à voir les nombres correctement, mais le problème est qu'on ne pointe pas à la bonne place, d'où très probablement un bug lors de la lecture de flottants 64 bits dans des fichiers enregistrés au format big-endian
êtes-vous d'accord avec ma conclusion ?
si oui, y-aurait-il moyen de signaler ce bug quelque part pour qu'il puisse être traité ?
d'avance merci
en complément, un petit programme qui permet de tester en big-endian et little-endian, la lecture du nombre flottant décrit ci-dessus
je suis amené ces temps-ci à relire des fichiers binaires enregistrés au format big-endian, ma distribution F14 tournant sur une plateforme Intel, donc little-endian, j'utilise Ghex pour m'aider à déboguer mon programme, mais comme vous allez le constater, j'ai rencontré quelques problèmes
à titre d'information, la version de ghex utilisée correspond au rpm suivant : ghex-2.24.0-5.fc13.x86_64
les données binaires à relire sont enregistrées dans des fichiers générés par LabVIEW, et contiennent des données au format cluster (un équivalent du struct C/C++), avec dans ce cluster, un tableau de nombres réels au format double (donc codé sur 64 bits)
à l'aide de LabVIEW, j'ai regénéré le fichier, à l'origine au format big-endian, pour l'enregistrer au format little-endian
dans ce format little-endian, voilà ce que Ghex me donne (voir première image ci-dessous)
- les 4 premiers octets (position 0x0=0) contiennent un nombre entier signé sur 32 bits (signed int) : c'est un numéro d'ordre, ici égal à 1
- 00 00 00 01 en little-endian donne donc le nombre 1
- les 4 octets suivants (position 0x4=4) contiennent un entier signé de 32 bits (signed int) : c'est un numéro d'ordre, ici égal à 21468
- 00 00 53 DC en little-endian donne donc le nombre 21468
- les 4 octets suivants (position 0x8=8) contiennent un entier signé de 32 bits (signed int) : c'est le nombre de lignes du tableau de double, ici égal à 100
- 00 00 00 64 en little-endian donne donc le nombre 100
- les 4 octets suivants (position 0xC=12) contiennent un entier signé de 32 bits (signed int) : c'est le nombre de colonnes du tableau de double, ici égal à 1
- 00 00 00 01 en little-endian donne donc le nombre 1
- les 8 octets suivants (position 0x10=16) contiennent le nombre au format double, donc 64 bits : c'est le premier nombre du tableau
- 40 97 FD 88 04 71 A2 C4 en little-endian donne donc le nombre 1535.383

la lecture se passe bien quant on relit le fichier au format little-endian, mais ça déraille quand on prend le fichier contenant les mêmes données, mais au format big-endian ; en effet, au lieu de 1535.383, on obtient 2,895473e-287 (voir image ci-dessous, avec l'option little-endian désactivée puisque les données contenues dans le fichier sont au format big-endian)
au format big-endian (et je l'ai vérifié par ailleurs avec un petit bout de programme C++, voir plus bas), le nombre signifie pourtant bien 1535.383
- nombre au format little endian
- 40 97 FD 88 04 71 A2 C4
- même nombre au format big endian
- C4 A2 71 04 88 FD 97 40
lecture erronée du nombre au format flottant 64 bits _type C double_ enregistré au format big-endian

Ghex m'a induit en erreur pendant pas mal de temps, c'est alors que j'ai remarqué qu'un décalage de 4 octets vers la gauche du pointeur de lecture de Ghex permettait alors d'afficher les nombres (situés en réalité 4 octets plus loin) au format flottant 64 bits de façon correcte
lecture "correcte" du nombre au format flottant 64 bits _type C double_ enregistré au format big-endian, seulement si un décalage de 4 octets à gauche est effectué

là aussi, si un décalage de 4 octets est effectué sur les 99 nombres flottants 64 bits suivants, on parvient à voir les nombres correctement, mais le problème est qu'on ne pointe pas à la bonne place, d'où très probablement un bug lors de la lecture de flottants 64 bits dans des fichiers enregistrés au format big-endian
êtes-vous d'accord avec ma conclusion ?
si oui, y-aurait-il moyen de signaler ce bug quelque part pour qu'il puisse être traité ?
d'avance merci
en complément, un petit programme qui permet de tester en big-endian et little-endian, la lecture du nombre flottant décrit ci-dessus
#include <iostream>
#include <cstdlib>
// ---------------------------------------------------
// convertit little-endian en big-endian et vice-versa
// ---------------------------------------------------
void
endian_swap_64(int64_t& x)
{
#ifdef __GNUC__
x = __builtin_bswap64(x);
#else
x = ((x<<56) & 0xFF00000000000000) | \
((x<<40) & 0x00FF000000000000) | \
((x<<24) & 0x0000FF0000000000) | \
((x<<8) & 0x000000FF00000000) | \
((x>>8) & 0x00000000FF000000) | \
((x>>24) & 0x0000000000FF0000) | \
((x>>40) & 0x000000000000FF00) | \
((x>>56) & 0x00000000000000FF);
#endif
}
// ---------------------------------------------------
// lit un mot de 64 bits en le mettant au bon format
// ---------------------------------------------------
unsigned char*
lecture_64(const bool little_endian, unsigned char *const ptr_chaine)
{
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
if (!little_endian) {
endian_swap_64(*reinterpret_cast<int64_t*>(ptr_chaine));
};
#else
if (little_endian) {
endian_swap_64(*reinterpret_cast<int64_t*>(ptr_chaine));
};
#endif
return (ptr_chaine);
}
// routine principale
int
main(void)
{
unsigned char chaine[8];
chaine[0] = 0xC4;
chaine[1] = 0xA2;
chaine[2] = 0x71;
chaine[3] = 0x04;
chaine[4] = 0x88;
chaine[5] = 0xFD;
chaine[6] = 0x97;
chaine[7] = 0x40;
std::cout<<"lecture au format little-endian : "<<*reinterpret_cast<double*>(lecture_64(true,chaine))<<std::endl;
chaine[0] = 0x40;
chaine[1] = 0x97;
chaine[2] = 0xFD;
chaine[3] = 0x88;
chaine[4] = 0x04;
chaine[5] = 0x71;
chaine[6] = 0xA2;
chaine[7] = 0xC4;
std::cout<<"lecture au format big-endian : "<<*reinterpret_cast<double*>(lecture_64(false,chaine))<<std::endl;
return (EXIT_SUCCESS);
}