Salut, je cherche à lire et écrire des données, mais je ne veux pas que les données soit lue ou écrite deux fois si un pointeur pointe sur une variable.
J'ai donc fais ceci :
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 int var = 5; int* pvar = &var; std::ofstream file; OTextArchive ota(file); ota(var); ota(pvar);
Dans l'archive, je stocke l'adresse de var que je fais correspondre à un id dans une std::map, j'écris l'id et le contenu de var, ensuite, je recherche l'adresse correspondant à l'id et j'écris uniquement l'id pour dire que j'ai un pointeur vers la var. (Je ne peut pas écrire les adresses car elles peuvent changer d'une exécution à l'autre du programme)
Lors de la lecture je fais l'inverse, c'est à dire que je lis l'id et le contenu de var, et je stocke l'adresse et l'id dans une std::map, ensuite, je lis l'id, et je recherche l'adresse correspondante dans la std::map que j'affecte au pointeur pvar.
Bref, le code ressemble à ceci pour l'écriture :
Code cpp : 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 /** * \fn void operator(T& data, D...) * \brief write a fundamental type into the archive. * \param T& the data to write. * \param D... used for SFINAE. */ template <typename T, class... D, class = typename std::enable_if<std::is_fundamental<T>::value>::type> void operator() (T& data, D...) { std::map<unsigned long long int, long long int>::iterator it = adresses.find(reinterpret_cast<long long int>(&data)); if (it != adresses.end()) { //Variable already written, write just the variable id. buffer<<it->second<<std::endl; } else { //Variable not writtent, write corresponding id and the variable's content. std::pair<unsigned long long int, long long int> newAddress (reinterpret_cast<long long int>(&data), nbSerialized); adresses.insert(newAddress); nbSerialized++; buffer<<newAddress.second<<std::endl; buffer<<data; } } /** * \fn void operator(T* data, D...) * \brief write pointer to a fundamental type into the archive. * \param T* the pointer to write. * \param D... used for SFINAE. */ template <typename T, class... D, class = typename std::enable_if<std::is_fundamental<T>::value>::type> void operator() (T* data, D...) { //Pointer not null, we can write the variable. if (data != nullptr) { std::map<unsigned long long int, long long int>::iterator it = adresses.find(reinterpret_cast<long long int>(data)); //The variable content has already been written, write just the variable's id. if (it != adresses.end()) { buffer<<it->second<<std::endl; //The variable content has not been writtent, write the variable's id and content. } else { std::pair<unsigned long long int, long long int> newAddress (reinterpret_cast<long long int>(data), nbSerialized); adresses.insert(newAddress); serialized++; buffer<<newAddress.second<<std::endl; buffer<<(*data); } //Pointer is null, write -1. } else { long long int id = -1; buffer<<id<<std::endl; } }
Lors de la lecture, je fais l'inverse :
Code cpp : 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 //Fundamentals. /** * \fn void operator(T& data, D...) * \brief read a fundamental type from the archive. * \param T& the data to read. * \param D... used for SFINAE. */ template <typename T, class... D, class = typename std::enable_if<std::is_fundamental<T>::value>::type> void operator() (T& data, D...) { long long int id; buffer>>id; char space; buffer.get(space); std::map<long long int, unsigned long long int>::iterator it = adresses.find(id); //Variable has already been read, we affect its address. if (it != adresses.end()) { //Error, it won't compile. &data = reinterpret_cast<T*> (it->second); //Variable has not been read yet, store its address and its id and read the variable's content. } else { std::pair<long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(data)); adresses.insert(newAddress); nbDeserialized++; buffer>>data; char space; buffer.get(space); } } /** * \fn void operator(T& data, D...) * \brief read a pointer to a fundamental type from the archive. * \param T& the data to read. * \param D... used for SFINAE. */ template <typename T, class... D, class = typename std::enable_if<std::is_fundamental<T>::value>::type> void operator() (T*& data, D...) { long long int id; buffer>>id; char space; buffer.get(space); if (id != -1) { //Variable has already been read, we affect its address. std::map<long long int, unsigned long long int>::iterator it = adresses.find(id); if (it != adresses.end()) { data = reinterpret_cast<T*> (it->second); //Variable has not been read yet, store its address and its id and read the variable's content. } else { std::pair<long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(data)); adresses.insert(newAddress); nbDeserialized++; data = new T(); buffer>>(*data); } } else { data = nullptr; } }
Dans le fichier j'ai donc ceci :
Écrit dans cet ordre là, pas de problème, par contre si je fais ça :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 0 5 //Variable id and content. 0 //Variable id. (pointer to first variable)
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 int var = 5; int* pvar = &var; std::ofstream file; OTextArchive ota(file); ota(pvar); ota(var);
Cela va poser problème car à la lecture il va allouer le pointeur pvar et lui donner la valeur 5, ensuite il va donner l'adresse du pointeur pvar à var.
Hors en c++ on ne peut pas faire ceci :
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 //Error, it won't compile. &data = reinterpret_cast<T*> (it->second);
Du coup je cherche un code en assembleur que j'insérerai dans le code c++ et qui me permettrait de changer l'adresse de la variable.
Mais je ne sais pas comment récupérer une référence vers la variable data dans le code assembleur pour changer son adresse et lui donner celle de mon pointeur.
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 asm { ? }
Est ce que quelqu'un sait comment faire ?
Merci d'avance.
Partager