C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Precision sur la "one definition rule"

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
Aurelien Regat-Barrel
Guest





PostPosted: Fri Mar 17, 2006 5:06 pm    Post subject: Precision sur la "one definition rule" Reply with quote



Bonjour,
J'ai eu affaire à un drôle de bug dans mon programme, provoqué par un
code de ce genre:

// montemplate.h
template<typename T>
class montemplate
{
#ifdef MODIF
// quelque chose
#else
// autre chose
#endif
};

// test.cpp
#define MODIF
#include "montemplate.h"

// utilisation de montemplate...


// main.cpp
#include "montemplate.h"

// utilisation de montemplate...


Je pensais pas que ce genre de code était problématique (unités de
compilations différentes), mais apparement si (dixit la one definition
rule).
Vous confirmez ?
Merci.

--
Aurélien Regat-Barrel
Back to top
Jean-Marc Bourguet
Guest





PostPosted: Fri Mar 17, 2006 5:06 pm    Post subject: Re: Precision sur la "one definition rule" Reply with quote



Aurelien Regat-Barrel <nospam.aregatba (AT) yahoo (DOT) fr> writes:

Quote:
Je pensais pas que ce genre de code était problématique (unités de
compilations différentes), mais apparement si (dixit la one definition
rule).
Vous confirmez ?

Oui. Ca peut ou pas causer des problemes suivant les modifications,
mais c'est a chaque fois du comportement indetermine. Pense par
exemple a

template <typename T>
class c {
public:
~c() {
#ifdef MODIF
delete[] m_;
#endif
}
private:
#ifdef MODIF
char* m_;
#endif
int k;
};

et que tu liberes dans l'unite avec MODIF un exemplaire alloue dans
une unite sans MODIF.

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Back to top
Rémy
Guest





PostPosted: Fri Mar 17, 2006 5:06 pm    Post subject: Re: Precision sur la "one definition rule" Reply with quote



"Aurelien Regat-Barrel" <nospam.aregatba (AT) yahoo (DOT) fr> a écrit dans le message
de news: 441ae3d7$0$31419$626a54ce (AT) news (DOT) free.fr...
Quote:
Bonjour,
J'ai eu affaire à un drôle de bug dans mon programme, provoqué par un code
de ce genre:

// montemplate.h
template<typename T
class montemplate
{
#ifdef MODIF
// quelque chose
#else
// autre chose
#endif
};

// test.cpp
#define MODIF
#include "montemplate.h"

// utilisation de montemplate...


// main.cpp
#include "montemplate.h"

// utilisation de montemplate...


Je pensais pas que ce genre de code était problématique (unités de
compilations différentes), mais apparement si (dixit la one definition
rule).
Vous confirmez ?
Merci.


Eh bien si "quelque chose" et "autre chose" sont suffisamment différents, il
y aura forcément un problème à l'édition de liens (lorsqu'on essaye de lier
ensemble test.o et main.o).
Back to top
kanze
Guest





PostPosted: Mon Mar 20, 2006 9:06 am    Post subject: Re: Precision sur la "one definition rule" Reply with quote

Aurelien Regat-Barrel wrote:
Quote:
Rémy a écrit :

Eh bien si "quelque chose" et "autre chose" sont
suffisamment différents, il y aura forcément un problème à
l'édition de liens (lorsqu'on essaye de lier ensemble test.o
et main.o).

Comme disait Jean-Marc, s'il y a la moindre différence, c'est un
comportement indéfini. La norme existe que le compilateur voit
exactement la même séquence de tokens dans toutes les unités de
traduction.

Dans la pratique, tout dépend. En général, tu peux bien utiliser
assert, par exemple, même si dans une unité de traduction,
NDEBUG est défini, et pas dans les autres. C'est un comportement
indéfini, mais dans la pratique, je vois mal le cas où il pose
un problème (sauf dans le cas où le compilateur vérifie les
violations de la ODR -- et il me semble que David Vandevoorte a
dit une fois que le front-end EDG en a une option pour le faire).

Quote:
Le problème est effectivement survenu à l'édition de liens,

Sois content. Moi, aussi, je l'ai rencontré, mais seulement à
l'exécution, quand le programme s'est mis à faire des cores
dumps inexplicables.

Quote:
mais pas de manière systématique (avec VC++ Cool. En DEBUG pas
de problème, en RELEASE sans optimisation globale non plus.
Avec optimisation globale (/GL), ça crée des problèmes.

Pour info, j'ai eu ce problème "à l'insu de mon plein grès"
avec std::vector sous VC++ 8 en définissant _SECURE_SCL à 0
dans 1 fichier de mon projet pour éviter d'avoir des warnings
(ailleurs que dans std::vector). Sauf que ça modifie pas mal
de choses dans std::vector aussi, et voilà.

_SECURE_SCL, ça ne serait pas un peu comme _GLIBCXX_DEBUG sous
G++ ? C'était exactement mon problème, sauf que ça linkait bien.
(Dans mon cas, c'était une erreur dans le fichier de make.
J'étais convaincu que je me servais des bibliothèques de debug,
alors que ce n'était pas le cas. J'avais un vecteur qui était
créer dans la bibliothèque, mais dont je me servais des
itérateurs dans une fonction templatée instantiée dans main.)

En régle générale : il faut que toutes les unités de compilation
soient compilées avec exactement les mêmes options, y compris
les mêmes -D. Et que tu ne définisses jamais de macro dans ton
code avant d'inclure les en-têtes, et que les en-têtes aussi ne
définissent que les macros qui les concernent.

Plus ou moins. Il y a des options qui spécifient les fichiers de
sortie, par exemple, et là, évidemment, il vaut mieux qu'elles
soient différentes d'une unité de compilation à l'autre:-). Des
variations dans le niveau d'avertissements ne doivent pas poser
de problèmes non plus. (Avec VC++, si tu fais cl /help, les
options dans « -OUTPUT FILES- », et quelques unes dans
« -MISCELLANEOUS- », vont bien. Les autres non.)

Il faut aussi se rappeler que certains compilateurs peuvent
instantier les templates lors de l'édition des liens, et que
dans ce cas-là, il faut passer aussi toutes les options à
l'édition de liens aussi. De même, certains compilateurs (Sun
CC, par exemple, mais probablement d'autres qui se servent d'un
repositoire) peuvent instantier les templates lors de la
génération des bibliothèques -- dans ce cas-là, il faut aussi
les mêmes options alors.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Mon Mar 20, 2006 9:06 am    Post subject: Re: Precision sur la "one definition rule" Reply with quote

Jean-Marc Bourguet a écrit :
Quote:
Oui. Ca peut ou pas causer des problemes suivant les modifications,
mais c'est a chaque fois du comportement indetermine. Pense par
exemple a

template <typename T
class c {
public:
~c() {
#ifdef MODIF
delete[] m_;
#endif
}
private:
#ifdef MODIF
char* m_;
#endif
int k;
};

et que tu liberes dans l'unite avec MODIF un exemplaire alloue dans
une unite sans MODIF.

Ca je comprends tout à fait. Là où je suis davantage surpris c'est si
les 2 unités ont chacune leur propre "version" et qu'elles ne se
mélangent pas.


--
Aurélien Regat-Barrel
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Mon Mar 20, 2006 9:06 am    Post subject: Re: Precision sur la "one definition rule" Reply with quote

Rémy a écrit :
Quote:
Eh bien si "quelque chose" et "autre chose" sont suffisamment différents, il
y aura forcément un problème à l'édition de liens (lorsqu'on essaye de lier
ensemble test.o et main.o).

Le problème est effectivement survenu à l'édition de liens, mais pas de
manière systématique (avec VC++ Cool. En DEBUG pas de problème, en RELEASE
sans optimisation globale non plus. Avec optimisation globale (/GL), ça
crée des problèmes.
Pour info, j'ai eu ce problème "à l'insu de mon plein grès" avec
std::vector sous VC++ 8 en définissant _SECURE_SCL à 0 dans 1 fichier de
mon projet pour éviter d'avoir des warnings (ailleurs que dans
std::vector). Sauf que ça modifie pas mal de choses dans std::vector
aussi, et voilà.

--
Aurélien Regat-Barrel
Back to top
Jean-Marc Bourguet
Guest





PostPosted: Mon Mar 20, 2006 9:06 am    Post subject: Re: Precision sur la "one definition rule" Reply with quote

Aurelien Regat-Barrel <nospam.aregatba (AT) yahoo (DOT) fr> writes:

Quote:
Jean-Marc Bourguet a écrit :
Oui. Ca peut ou pas causer des problemes suivant les modifications,
mais c'est a chaque fois du comportement indetermine. Pense par
exemple a
template <typename T
class c {
public:
~c() { #ifdef MODIF
delete[] m_;
#endif
}
private:
#ifdef MODIF
char* m_;
#endif
int k;
};
et que tu liberes dans l'unite avec MODIF un exemplaire alloue dans
une unite sans MODIF.

Ca je comprends tout à fait. Là où je suis davantage surpris c'est si les 2
unités ont chacune leur propre "version" et qu'elles ne se mélangent pas.

En es-tu sur qu'il n'y a pas de melange (du genre partage de code)?

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Mon Mar 20, 2006 10:06 am    Post subject: Re: Precision sur la "one definition rule" Reply with quote

Jean-Marc Bourguet a écrit :
Quote:
Ca je comprends tout à fait. Là où je suis davantage surpris c'est si les 2
unités ont chacune leur propre "version" et qu'elles ne se mélangent pas.


En es-tu sur qu'il n'y a pas de melange (du genre partage de code)?

Le problème surgit avec l'option d'optimisation globale (/GL) qui en
gros compile tout les différents fichiers sources comme si c'était un
seul fichier unique.
Je cherche à savoir si cette erreur est une conséquence de cette
optimisation globale, ou si c'est juste la manifestation d'un problème
qui relève bien du code. Cette histoire de template instanciée de
manière identique à l'ensemble des codes sources compilés, ça fait un
peu effet de bord je trouve...

--
Aurélien Regat-Barrel
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Mon Mar 20, 2006 11:06 am    Post subject: Re: Precision sur la "one definition rule" Reply with quote

kanze a écrit :

Quote:
Le problème est effectivement survenu à l'édition de liens,


Sois content. Moi, aussi, je l'ai rencontré, mais seulement à
l'exécution, quand le programme s'est mis à faire des cores
dumps inexplicables.

Oups pardon. Mon exe s'est bien linké sans problèmes, et j'ai bien eu un
comportement incompréhensible au runtime, puis des plantages biensûr.
J'ai voulu dire que c'est l'éditeur de liens qui s'est embrouillé dans
son travail.

Quote:
mais pas de manière systématique (avec VC++ Cool. En DEBUG pas
de problème, en RELEASE sans optimisation globale non plus.
Avec optimisation globale (/GL), ça crée des problèmes.


Pour info, j'ai eu ce problème "à l'insu de mon plein grès"
avec std::vector sous VC++ 8 en définissant _SECURE_SCL à 0
dans 1 fichier de mon projet pour éviter d'avoir des warnings
(ailleurs que dans std::vector). Sauf que ça modifie pas mal
de choses dans std::vector aussi, et voilà.


_SECURE_SCL, ça ne serait pas un peu comme _GLIBCXX_DEBUG sous
G++ ? C'était exactement mon problème, sauf que ça linkait bien.
(Dans mon cas, c'était une erreur dans le fichier de make.
J'étais convaincu que je me servais des bibliothèques de debug,
alors que ce n'était pas le cas. J'avais un vecteur qui était
créer dans la bibliothèque, mais dont je me servais des
itérateurs dans une fonction templatée instantiée dans main.)

Dans mon cas c'est un peu plus pervers : c'est la fonctions inline qui
manipulait un vector (std::max_element) renvoyé par une fonction non
inline qui provoquait le problème.

Quote:
En régle générale : il faut que toutes les unités de compilation
soient compilées avec exactement les mêmes options, y compris
les mêmes -D. Et que tu ne définisses jamais de macro dans ton
code avant d'inclure les en-têtes, et que les en-têtes aussi ne
définissent que les macros qui les concernent.

J'ai enfreint ce principe dans un seul fichier de tout le projet, et
voilà :-)

Quote:
Plus ou moins. Il y a des options qui spécifient les fichiers de
sortie, par exemple, et là, évidemment, il vaut mieux qu'elles
soient différentes d'une unité de compilation à l'autre:-). Des
variations dans le niveau d'avertissements ne doivent pas poser
de problèmes non plus. (Avec VC++, si tu fais cl /help, les
options dans « -OUTPUT FILES- », et quelques unes dans
« -MISCELLANEOUS- », vont bien. Les autres non.)

Il faut aussi se rappeler que certains compilateurs peuvent
instantier les templates lors de l'édition des liens, et que
dans ce cas-là, il faut passer aussi toutes les options à
l'édition de liens aussi. De même, certains compilateurs (Sun
CC, par exemple, mais probablement d'autres qui se servent d'un
repositoire) peuvent instantier les templates lors de la
génération des bibliothèques -- dans ce cas-là, il faut aussi
les mêmes options alors.

Là j'ai eu le problème avec l'option /GL qui fait que la compilation
n'est pas complète mais est terminée par le linker (qui rappelle le
compilo). Je suppose que dans cette configuration les templates sont
instanciés à l'édition de liens.
Aucun problème en fonctionnement "classique".

--
Aurélien Regat-Barrel
Back to top
Jean-Marc Bourguet
Guest





PostPosted: Mon Mar 20, 2006 11:06 am    Post subject: Re: Precision sur la "one definition rule" Reply with quote

Aurelien Regat-Barrel <nospam.aregatba (AT) yahoo (DOT) fr> writes:

Quote:
Jean-Marc Bourguet a écrit :
Ca je comprends tout à fait. Là où je suis davantage surpris c'est si les 2
unités ont chacune leur propre "version" et qu'elles ne se mélangent pas.
En es-tu sur qu'il n'y a pas de melange (du genre partage de code)?

Le problème surgit avec l'option d'optimisation globale (/GL) qui en
gros compile tout les différents fichiers sources comme si c'était
un seul fichier unique.

Ca ne me semble pas etonnant que des problemes ne se relevent qu'avec
ce genre d'options.

Quote:
Je cherche à savoir si cette erreur est une conséquence de cette
optimisation globale, ou si c'est juste la manifestation d'un
problème qui relève bien du code.

Si on joue le jeu formel, ca releve du code: tu n'as pas respecte une
des regles. Si tu veux comprendre pourquoi dans ton exemple
l'optimiseur agit comme il le fait, sans voir le code c'est difficile.
En general avec les optimiseurs, plus ils sont pousses, plus ils ont
l'air d'aller chercher des informations n'importe ou, parfois de
maniere surprenante.

Je crois que j'ai deja donne ce genre d'exemples (je ne l'ai pas vecu,
je ne sais plus si je l'ai vu comme etant le comportement d'un
optimiseur reel ou bien dans un contexte similaire de celui-ci ou
quelqu'un donnait un exemple de comportement possible d'un optimiseur
sans pretendre qu'il y en a un actuellement le faisant):

if (ptr == NULL && logging_activated) {
log << "Pointer is null\n";
}
ptr->f();

ou l'optimiseur considerant que ptr->f() n'est du comportement defini
que si ptr est non nul deduit que ptr est non null donc que le test
dans le if est une constante fausse et vire le if et la branche
loggant le fait que ptr est nul. Un probleme arrive et ptr est nul.
Pas d'info dans la trace et retrouver la cause du probleme est un peu
plus complique que si l'optimiseur avait ete moins malin.

Quote:
Cette histoire de template instanciée de manière identique à
l'ensemble des codes sources compilés, ça fait un peu effet de bord
je trouve...

On pourrait desirer que le non respect de l'ODR soit detecte, mais a
part ca je vois mal ce que tu veux. Tu peux mettre la definition du
template dans un namespace anonyme, mais alors tu ne peux plus
passer tes objets d'une unite de compilation a l'autre.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Mon Mar 20, 2006 2:06 pm    Post subject: Re: Precision sur la "one definition rule" Reply with quote

Jean-Marc Bourguet a écrit :
Quote:
Cette histoire de template instanciée de manière identique à
l'ensemble des codes sources compilés, ça fait un peu effet de bord
je trouve...


On pourrait desirer que le non respect de l'ODR soit detecte, mais a
part ca je vois mal ce que tu veux. Tu peux mettre la definition du
template dans un namespace anonyme, mais alors tu ne peux plus
passer tes objets d'une unite de compilation a l'autre.

Je veux juste comprendre. J'ai fait une erreur, je cherche pas à ce
qu'elle soit acceptée. Par contre j'aurai bien aimé qu'elle soit détectée.
Pour te donner une idée de code qui crash sous VC++ 8 :

// test.cpp
#define _SECURE_SCL 0
#include <vector>
#include <algorithm>

void test()
{
std::vector<int> v( 150, 10 );
std::vector<int>::iterator max_i =
std::max_element( v.begin(), v.end() );
int max = *max_i;
}

// main.cpp
#include <vector>
template class std::vector<int, std::allocator< int > >;

void test();

int main()
{
test();
return 0;
}

Pas besoin de passer des instances de std::vector entre les unités de
compilation, la spécialisation explicite dans main.cpp suffit. Et si
c'est main.cpp qui définit _SECURE_SCL à 0, ça marche...

En fait _SECURE_SCL influence sur le type de l'itérateur. Je me demande
s'il serait possible de provoquer des erreurs à l'édition des liens si
l'ODR n'était pas respectée.

--
Aurélien Regat-Barrel
Back to top
Jean-Marc Bourguet
Guest





PostPosted: Mon Mar 20, 2006 2:06 pm    Post subject: Re: Precision sur la "one definition rule" Reply with quote

Aurelien Regat-Barrel <nospam.aregatba (AT) yahoo (DOT) fr> writes:

Quote:
Jean-Marc Bourguet a écrit :
Cette histoire de template instanciée de manière identique à
l'ensemble des codes sources compilés, ça fait un peu effet de bord
je trouve...
On pourrait desirer que le non respect de l'ODR soit detecte, mais a
part ca je vois mal ce que tu veux. Tu peux mettre la definition du
template dans un namespace anonyme, mais alors tu ne peux plus
passer tes objets d'une unite de compilation a l'autre.

Je veux juste comprendre. J'ai fait une erreur, je cherche pas à ce qu'elle
soit acceptée. Par contre j'aurai bien aimé qu'elle soit détectée.
Pour te donner une idée de code qui crash sous VC++ 8 :

// test.cpp
#define _SECURE_SCL 0
#include <vector
#include <algorithm

void test()
{
std::vector<int> v( 150, 10 );
std::vector<int>::iterator max_i =
std::max_element( v.begin(), v.end() );
int max = *max_i;
}

// main.cpp
#include <vector
template class std::vector<int, std::allocator< int > >;

void test();

int main()
{
test();
return 0;
}

Pas besoin de passer des instances de std::vector entre les unités de
compilation, la spécialisation explicite dans main.cpp suffit.

Ce qui se passe vraissemblablement ici c'est que tu as des membres
inlines dans test.cpp qui utilisent une structure pour
std::vector<int> qui suppose _SECURE_SCL a 0. Dans test.cpp il y a
aussi des appels a des membres non inlines qui dans le cas de
l'optimisation globale sont prises dans main.cpp et qui donc supposent
_SECURE_SCL non definis. Rien n'empecherait l'editeur de liens de
faire le meme choix sans l'optimisation globale, ou meme en debug...

Quote:
Et si c'est main.cpp qui définit _SECURE_SCL à 0, ça marche...

Il suffit que la version choisie paraisse marcher. Soit que l'editeur
fasse un autre choix et choisisse la version dans test.cpp, soit que
par hasard la fonction avec _SECURE_SCL fonctionne dans les deux cas,
soit qu'il y a un probleme de corruption ou autre que tu n'as pas
detecte sur un exemple aussi simple.

Quote:
Je me demande s'il serait possible de provoquer des erreurs à
l'édition des liens si l'ODR n'était pas respectée.

Je ne vois rien a faire que de subir ce que fait l'implementation pour
qui ne la controle pas. Si tu controles l'implementation, c'est
possible avec un editeur de liens suffisemment sophistique (ce qui ne
le serait pas beaucoup). Il "suffirait" d'emettre dans chaque unite
de compilation qui voit (ou utilise simplement si on veut etre moins
strict) la definition d'un type une signature de la partie
significative du type et que l'editeur de liens verifie que tous les
types ont bien la meme signature dans toutes les unites de
compilation. C'est pas complique. La partie Ada de GCC fait plus ou
moins l'equivalent pour l'Ada (ils utilisaient d'autres fichiers que
les .o la derniere fois que j'ai regarde, mais rien n'empeche de
mettre cette info dans les .o et il me semble que la doc faisait
allusion a cette possibilite).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Tue Mar 21, 2006 9:06 am    Post subject: Re: Precision sur la "one definition rule" Reply with quote

Jean-Marc Bourguet a écrit :

Quote:
Pas besoin de passer des instances de std::vector entre les unités de
compilation, la spécialisation explicite dans main.cpp suffit.


Ce qui se passe vraissemblablement ici c'est que tu as des membres
inlines dans test.cpp qui utilisent une structure pour
std::vector<int> qui suppose _SECURE_SCL a 0. Dans test.cpp il y a
aussi des appels a des membres non inlines qui dans le cas de
l'optimisation globale sont prises dans main.cpp et qui donc supposent
_SECURE_SCL non definis. Rien n'empecherait l'editeur de liens de
faire le meme choix sans l'optimisation globale, ou meme en debug...


Et si c'est main.cpp qui définit _SECURE_SCL à 0, ça marche...


Il suffit que la version choisie paraisse marcher. Soit que l'editeur
fasse un autre choix et choisisse la version dans test.cpp, soit que
par hasard la fonction avec _SECURE_SCL fonctionne dans les deux cas,
soit qu'il y a un probleme de corruption ou autre que tu n'as pas
detecte sur un exemple aussi simple.


Je me demande s'il serait possible de provoquer des erreurs à
l'édition des liens si l'ODR n'était pas respectée.


Je ne vois rien a faire que de subir ce que fait l'implementation pour
qui ne la controle pas. Si tu controles l'implementation, c'est
possible avec un editeur de liens suffisemment sophistique (ce qui ne
le serait pas beaucoup). Il "suffirait" d'emettre dans chaque unite
de compilation qui voit (ou utilise simplement si on veut etre moins
strict) la definition d'un type une signature de la partie
significative du type et que l'editeur de liens verifie que tous les
types ont bien la meme signature dans toutes les unites de
compilation. C'est pas complique. La partie Ada de GCC fait plus ou
moins l'equivalent pour l'Ada (ils utilisaient d'autres fichiers que
les .o la derniere fois que j'ai regarde, mais rien n'empeche de
mettre cette info dans les .o et il me semble que la doc faisait
allusion a cette possibilite).

Merci pour ces explications.

--
Aurélien Regat-Barrel
Back to top
kanze
Guest





PostPosted: Tue Mar 21, 2006 9:06 am    Post subject: Re: Precision sur la "one definition rule" Reply with quote

Aurelien Regat-Barrel wrote:
Quote:
kanze a écrit :

Pour info, j'ai eu ce problème "à l'insu de mon plein grès"
avec std::vector sous VC++ 8 en définissant _SECURE_SCL à 0
dans 1 fichier de mon projet pour éviter d'avoir des
warnings (ailleurs que dans std::vector). Sauf que ça
modifie pas mal de choses dans std::vector aussi, et voilà.

_SECURE_SCL, ça ne serait pas un peu comme _GLIBCXX_DEBUG
sous G++ ? C'était exactement mon problème, sauf que ça
linkait bien. (Dans mon cas, c'était une erreur dans le
fichier de make. J'étais convaincu que je me servais des
bibliothèques de debug, alors que ce n'était pas le cas.
J'avais un vecteur qui était créer dans la bibliothèque,
mais dont je me servais des itérateurs dans une fonction
templatée instantiée dans main.)

Dans mon cas c'est un peu plus pervers : c'est la fonctions
inline qui manipulait un vector (std::max_element) renvoyé par
une fonction non inline qui provoquait le problème.

Ce qui revient au même. L'important, c'est que l'instance de
vector s'est fait (allocation et appel du constructeur) dans une
contexte sans le debug, et l'utilisation dans une contexte avec.

En gros, le but de _GLIBCXX_DEBUG (et, je suppose, de
_SECURE_SCL), c'est de détecter des erreurs du genre utilisation
d'un itérateur invalid. Quand tu effectues une opération qui
peut invalider un itérateur (comme par exemple push_back sur un
vector), tous les itérateurs sont marqués invalides, et si on
essaie d'utiliser un itérateur marqué invalide, tu as une erreur
claire et nette (et immédiate). Pour pouvoir marquer les
itérateurs, en revanche, il faut bien qu'on puisse les trouver à
partir du vector -- dans l'implémentation g++, les itérateurs se
trouvent tous dans une liste chaîné dont la racine se trouve
dans le vecteur. Si le vecteur est construit dans une contexte
sans _GLIBCXX_DEBUG, il ne contient pas cette racine, et si on
construit ou copie un itérateur dans une contexte avec
_GLIBCXX_DEBUG, on déréférence des pointeurs dans cette racine
qui n'y est pas (et qui donc n'a pas été initialisée).

Quote:
En régle générale : il faut que toutes les unités de
compilation soient compilées avec exactement les mêmes
options, y compris les mêmes -D. Et que tu ne définisses
jamais de macro dans ton code avant d'inclure les en-têtes,
et que les en-têtes aussi ne définissent que les macros qui
les concernent.

J'ai enfreint ce principe dans un seul fichier de tout le
projet, et voilà Smile

Moi aussi, il n'y avait qu'un seul fichier compilé avec debug.
En plus, ce fichier n'utilisait même pas les itérateurs. Mais il
utilisait un template qui les utilisait, et l'instantiation du
template s'est fait dans la contexte du fichier compilé avec
debug.

J'ai eu un mal fou à trouver l'erreur, parce que j'étais
convaincu de me servir des bibliothèques de debug, et il ne
m'était pas venu à l'esprit de vérifier le fichier de make.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Back to top
Aurelien Regat-Barrel
Guest





PostPosted: Tue Mar 21, 2006 10:06 am    Post subject: Re: Precision sur la "one definition rule" Reply with quote

kanze a écrit :

Quote:
Dans mon cas c'est un peu plus pervers : c'est la fonctions
inline qui manipulait un vector (std::max_element) renvoyé par
une fonction non inline qui provoquait le problème.


Ce qui revient au même. L'important, c'est que l'instance de
vector s'est fait (allocation et appel du constructeur) dans une
contexte sans le debug, et l'utilisation dans une contexte avec.

En gros, le but de _GLIBCXX_DEBUG (et, je suppose, de
_SECURE_SCL), c'est de détecter des erreurs du genre utilisation
d'un itérateur invalid. Quand tu effectues une opération qui
peut invalider un itérateur (comme par exemple push_back sur un
vector), tous les itérateurs sont marqués invalides, et si on
essaie d'utiliser un itérateur marqué invalide, tu as une erreur
claire et nette (et immédiate). Pour pouvoir marquer les
itérateurs, en revanche, il faut bien qu'on puisse les trouver à
partir du vector -- dans l'implémentation g++, les itérateurs se
trouvent tous dans une liste chaîné dont la racine se trouve
dans le vecteur. Si le vecteur est construit dans une contexte
sans _GLIBCXX_DEBUG, il ne contient pas cette racine, et si on
construit ou copie un itérateur dans une contexte avec
_GLIBCXX_DEBUG, on déréférence des pointeurs dans cette racine
qui n'y est pas (et qui donc n'a pas été initialisée).

J'ai pas pris le temps d'étudier le but exact de _SECURE_SCL par rapport
à _HAS_ITERATOR_DEBUGGING. Dans le cadre de std::vector, pour ce que
j'en ai vu c'est à peu près pareil. J'avais défini _SECURE_SCL à 0 afin
d'utiliser <algorithm> sans avoir de warnings comme quoi std::transform
"a été déclaré désapprouvé".
Message : 'You have used a std:: construct that is not safe. See
documentation on how to use the Safe Standard C++ Library'

Mais pas de bol j'avais un include <vector> en dessous...

Merci.

--
Aurélien Regat-Barrel
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.