Bonjour à tous,
Ces quelques derniers jours, j'ai dépoussiéré un projet réalisé il y a 2 ou 3 ans sous linux (dont on retrouvera des vestiges dans différents posts sur ce forum), nécessitant la lecture de fichiers de type *.idx.
Sans grande surprises, à la lecture du code réalisé à l'époque, ce dernier nécessite une totale refactorisation compte tenu de ma prise de maturité dans le langage depuis (merci au forum !!!).
Je m'y plonge donc, et, cette fois-ci par contre, grande surprise ! La sortie fournie par l'outil ne correspond pas à celle attendue (censée être finalement la même que le code initial).
Je retourne donc le code dans tous les sens, essaie d'autres méthodes, m'assure plutôt 10 fois qu'une que l'algorithme est viable etc... Bref, le code qui devais être une mise au propre devient alors un code de test... Rien y fait. En 3 jours de recherche, même le code initial qui me servait de base recrache toujours la même chose : une sortie tronquée (pas fausse, tronquée ; une partie des infos semble corrompue) par rapport à ce qui est attendu.
Je me dit, "ok, j'utilise GCC en powershell, peut-être que le sujet vient du compilo". J'installe donc Code::Blocks (ayant formaté il y a peu, avec windows on en prends l'habitude) et là, le résultat est exactement le même (normal ; MINGW = GCC).
Ayant eu des soucis lors de l'installation de code-blocks (pas sure du compilateur utilisé) et n'arrivant pas à le désinstaller complètement, je formate donc (encore... Pauvre SSD....) et test à nouveau avec code-blocks sur une installation brute (+ mises à jour windows et Drivers). Résultat. Toujours le bug.
Je réfléchis donc encore un peu : "le code de base fonctionnait à l'époque, moche, lent, absolument pas optimisé, mais les sorties étaient correctes et faisaient le taff. Je vais tester mon nouveau code (finalement à refaire quand même suite aux modifications vues précédemment mais bon) sur mon ancienne machine". Et là, illumination. Tout fonctionne nickel.
Verdict surprenant : le bug que j'ai, ne faisant appel qu'à des fonctions de base de la STL, est erratique sous Windows et fonctionne très bien sous Débian !! Pourquoi ???
Pour info, le code ne fait que charger 60'000 "images" de 28 pix * 28 pix au format IDX dans un vecteur lui même encapsulé dans une structure, et m'affiche à la demande l'image n° X ou Y. Je ne fais donc qu'intervenir des for, std::vector et std::fstream.
Le code complet étant suffisamment long pour n'avoir que peu d'intérêt ici, je ne mettrais que les parties "intéressantes". Bien entendu, si vous souhaitez en voir l'intégralité, il suffit de demander (finalement, on en est pas loin):
La déclaration de la classe principale (et des structures sous-jacentes) :
Rien de bien méchant jusque là...
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 #pragma once #include <cstdlib> #include <string> #include <vector> #include <iostream> #include <fstream> struct LabelSet { size_t magic; size_t size; std::vector<unsigned char> labels; }; struct PictureSet { size_t magic; size_t size; size_t rowDim; size_t colDim; //std::vector<std::vector<std::vector<unsigned char> > > pictures; std::vector<std::vector<unsigned char> > pictures; }; enum TYPE_SET { IDX_LABEL, IDX_PICTURE }; class IDX_Reader { private: LabelSet mLabel; PictureSet mPicture; public: IDX_Reader(); void load(TYPE_SET const & SET, std::string const & path); void loadLabel(std::fstream & labelFile); void loadPicture(std::fstream & pictureFile); void read(size_t const id); }; // EOF
Les déclarations des deux principales fonctions utilisées (en tout cas celles que j'estime pouvant être à l'origine du bug) :
Et, je mettrais bien une extraction des sorties attendues (fournies par la fonction IDX_Reader::read(size_t const id)) mais je dois encore ré-installer virtual-box et / ou trouver une manière de reproduire une version buguée et une non buguée sur la même machine...
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 void IDX_Reader::loadPicture(std::fstream & pictureFile) { mPicture.magic = (pictureFile.get() << 24) | (pictureFile.get() << 16) | (pictureFile.get() << 8) | pictureFile.get(); mPicture.size = (pictureFile.get() << 24) | (pictureFile.get() << 16) | (pictureFile.get() << 8) | pictureFile.get(); mPicture.rowDim = (pictureFile.get() << 24) | (pictureFile.get() << 16) | (pictureFile.get() << 8) | pictureFile.get(); mPicture.colDim = (pictureFile.get() << 24) | (pictureFile.get() << 16) | (pictureFile.get() << 8) | pictureFile.get(); //case of 2D vector mPicture.pictures.clear(); mPicture.pictures.resize(mPicture.size); for(auto & pic:mPicture.pictures) { pic.resize(mPicture.rowDim * mPicture.colDim, 0); for(auto & pix:pic) { pix = static_cast<unsigned char>(pictureFile.get()); } } // case of 3D vector /*mPicture.pictures.clear(); mPicture.pictures.resize(mPicture.size); for(auto & pic:mPicture.pictures) { pic.resize(mPicture.rowDim); for(auto & row:pic) { row.resize(mPicture.colDim, 0); for(auto & col:row) { col = static_cast<unsigned char>(pictureFile.get()); } } }*/ } void IDX_Reader::read(size_t const id) { std::cout << "Printing picture of index " << id << '\n'; std::cout << "Label : " << static_cast<unsigned short>(mLabel.labels[id]) << '\n'; // case of 2D vector for(size_t r{0}; r != mPicture.rowDim; ++r) { for(size_t c{0}; c != mPicture.colDim; ++c) { if(mPicture.pictures[id][c + (r * mPicture.colDim)] > 0) { std::cout << 'x'; } else { std::cout << ' '; } } std::cout << '\n'; } // case of 3D vector /*for(auto & row:mPicture.pictures[id]) { for(auto & col:row) { if(col > 0) { std::cout << 'x'; } else { std::cout << ' '; } } std::cout << '\n'; }*/ }
Mais globalement, les images (en niveau de gris [0 - 255]) doivent apparaitre à l'écran en mode console (voir algo de la fonction IDX_Reader::read(size_t const id)). Mais sous windows, à partir de la moitié de l'image 5, l'affichage apparait comme si les pictureFile.get() n'étaient pas faits (toutes les valeurs sont à 0, 255 si non défini dans le resize).
Dernière précision, sur mes deux machines, unsigned char = 8bits // int = 32 bits, les processeurs sont intel (des core I-7 86-64 sur les deux même si pas de même génération). Rappel : Intel = Litle Endian
Une idée de comment compiler ça sous windows ? A mon avis, au prochain format, je repasse sous Buster + XFCE4....
Merci d'avance !
Partager