Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2879 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  variable globale, problème de link

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

variable globale, problème de link

n°839403
glaurung
Posté le 02-09-2004 à 08:51:37  profilanswer
 

Bonjour, j'ai un autre problème à vous soumettre :
 
Plutôt que de définir des constantes fixes dans mon programme, j'ai créé un fichier dans lesquelles elles sont réunies, de façon à ce que chaque utilisateur puisse avoir son propre fichier de configuration avec des valeurs différentes.
 
Pour introduire ces données dans le programme, j'ai créé une structure dont chaque champ correspond à un paramètre de configuration. Par exemple nom_structure.szDefaultPathName etc. j'ai ensuite une fonction qui prends comme argument une de ces structures, et remplis les champs en fonction du fichier.
Vu que j'ai besoin d'accéder au champs de cette structure dans tous le programme (c'est à dire dans toutes les classes, à chaque fois qu'un des paramètres constant provenant du fichier doit être insérer), j'ai créé une variable globale de la structure d'initialisation, et je l'utilise parout où c'est nécessaire.
J'ai un fichier init.h avec la définition de la structure, le prototype de la fonction d'initialisation, et la déclaration de la variable globale du type de la structure. Le fichier init.cpp contient l'implémentation de la fonction d'initialisation.
 
Pas de problèmes de compilation, mais au moment du linkage, j'obtiens des messages d'erreur du genre :  
Cpmdiag.obj : error LNK2005: "struct s_ini init_data" (?init_data@@3Us_ini@@A) already defined in cpm.obj
 
Mais struct s_ini init_data n'est DEFINIE que dans le fichier init.h, dans les autres fichiers, cette variable globale est utilisée, mais pas redéfinie...
j'utilise VC++6.0, et en configuration DEBUG, le programme est quand même créé (comme s'il s'agissait plus de warnings que d'erreur), mais en RELEASE, pas question de finir le linkage...
 
Ou me suis-je trompé?

mood
Publicité
Posté le 02-09-2004 à 08:51:37  profilanswer
 

n°839475
Taz
bisounours-codeur
Posté le 02-09-2004 à 10:17:31  profilanswer
 

rien compris, balance du code (3 lignes et pas plus)

n°839515
glaurung
Posté le 02-09-2004 à 10:36:06  profilanswer
 

Taz a écrit :

rien compris, balance du code (3 lignes et pas plus)


 :pfff:  
 
init.h :
struct s_ini{
 int nCalib;
 BOOL bHtmlResume;
 string szFilePath;
 double dEvUrbach0;
 double dEvUrbach1;
 double dEvdefauts;
 double dEvcrist;
 int nType;
};
void read_init_file(struct s_ini & init, string szFileName="x" ); //fonction qui remplis les champs d'une struct
struct s_ini init_data; //déclaration variable globale
 
///////////////////////////////////////////
init.cpp
 
initialisation de la variable globale :
 
BOOL CEx06aView::PreCreateWindow(CREATESTRUCT& cs)
{
 // TODO: Modify the Window class or styles here by modifying
 //  the CREATESTRUCT cs
 read_init_file(init_data);
 return CView::PreCreateWindow(cs);
}
 
Puis par exemple, dans diverses classes, appel aux données de cette structure :
 
void CEx06aView::OnCpm()  
{
//blabla  
index_urbach0=c.get_ev_index(init_data.dEvUrbach0);
index_urbach1=c.get_ev_index(init_data.dEvUrbach1);
//blabla
}
mais dans les methode des classe, cette variable globale est utilisée, et non définie...
 
(bon je sais, 3 lignes    :D  )

n°839519
pains-aux-​raisins
Fatal error
Posté le 02-09-2004 à 10:42:14  profilanswer
 

1/ dans init.h : pas de déclaration de la variable globale init_data
2/ dans init.cpp : tu déclare struct s_ini init_data;
3/ dans les autres cpp : tu déclare extern struct s_ini init_data;


Message édité par pains-aux-raisins le 02-09-2004 à 10:46:53
n°839547
lsdYoYo
gravity powered
Posté le 02-09-2004 à 11:08:53  profilanswer
 

+1
Pour éviter d'avoir à redéclarer X fois "extern xxx" dans tous les cpp, un truc : la compile conditionnelle.
 

Code :
  1. init.h
  2. .../...
  3. #ifdef ALLOC_GLOBAL
  4. int toto;
  5. int tata = 93893;     //Avec une valeur de départ  
  6. MaStruct titi;
  7. #else
  8. extern int toto;
  9. extern int tata;      //!!! Ne pas redonner de valeur avec "extern"
  10. extern MaStruct titi;
  11. #endif


 

Code :
  1. init.cpp
  2. #define ALLOC_GLOBAL
  3. #include "init.h"
  4. .../...


 

Code :
  1. <autres modules cpp>
  2. //pas de #define ALLOC_GLOBAL avant #include "init.h"
  3. #include "init.h"
  4. .../...


 
L'autre (gros) avantage, c'est que tes déclarations (allocation et référence "extern" ) sont regroupées dans le même fichier. Quand tu modifie d'un côté, la modif parallèle se trouve juste en dessous. :sol:  
Sinon bonjour les dégats si les deux ne correspondent pas...


---------------
If I want to fail and succeed, which I have done ?
n°839551
pains-aux-​raisins
Fatal error
Posté le 02-09-2004 à 11:12:54  profilanswer
 

+1 :love:
 
Déjà qu'il assimile cette histoire de variable globale et ce sera bien.

n°839569
Taz
bisounours-codeur
Posté le 02-09-2004 à 11:29:23  profilanswer
 

  1. init.h
   2. .../...
   3. #ifdef ALLOC_GLOBAL
   4. int toto;
   5. int tata = 93893;     //Avec une valeur de départ  
   6. MaStruct titi;
   7. #else
   8. extern int toto;
   9. extern int tata;      //!!! Ne pas redonner de valeur avec "extern"
  10. extern MaStruct titi;
  11. #endif
 
 
 
c'est complètement pourri ta façon de procéder, c'est source d'erreur
 
un .h avec les déclarations extern, un .cpp avec l'allocation des variables :o

n°839622
Lam's
Profil: bas.
Posté le 02-09-2004 à 12:16:49  profilanswer
 

Taz a écrit :

1. init.h
c'est complètement pourri ta façon de procéder, c'est source d'erreur
 
un .h avec les déclarations extern, un .cpp avec l'allocation des variables :o


 
+1.  
 
Encore mieux, serait de passer par une fonction qui te renvoie un singleton. Du style:  
 

Code :
  1. s_struct * getStructure ()
  2. {
  3.   static s_struct * instance = 0;
  4.   if (!instance)
  5.      instance = new s_struct;
  6.   return instance;   
  7. }


 
Ca évite pas mal de problèmes lors de l'utilisation de l'instance avant le démarrage de main().
 
Edit: j'avais oublié un type.


Message édité par Lam's le 02-09-2004 à 12:17:38
n°839726
glaurung
Posté le 02-09-2004 à 13:21:01  profilanswer
 

Merci pour votre aide, je vais essayer.
C'est vrai que les variables globales je ne maîtrise pas, car je m'en suis toujours passé jusqu'à présent...
 
EDIT :  
j'ai utilisé la technique de pains-aux-raisins, et ça marche très bien. J'avais complétement oublié le coup du external. Encore merci


Message édité par glaurung le 02-09-2004 à 13:54:33
n°839778
blackgodde​ss
vive le troll !
Posté le 02-09-2004 à 13:51:56  profilanswer
 

Sur l'exemple de Lam's : et la struct on la libère pas ?
 
http://forum.hardware.fr/hardwaref [...] 5867-1.htm


---------------
-( BlackGoddess )-
mood
Publicité
Posté le 02-09-2004 à 13:51:56  profilanswer
 

n°839781
Taz
bisounours-codeur
Posté le 02-09-2004 à 13:53:35  profilanswer
 

bien essayé, mais n'attends pas trop de quelqu'un qui ne manipule que des struct ...

n°839797
Lam's
Profil: bas.
Posté le 02-09-2004 à 14:01:53  profilanswer
 

BlackGoddess a écrit :

Sur l'exemple de Lam's : et la struct on la libère pas ?
 
http://forum.hardware.fr/hardwaref [...] 5867-1.htm


 
Bof, ça sert à rien de la détruire si sa durée de vie est celle du programme. Sinon, tu rajoutes ça dans ton cpp

Code :
  1. namespace
  2. {
  3.   struct Cleaner
  4.   {
  5.     ~Cleaner() { delete getStructure(); }
  6.   }
  7.   Cleaner cleaner;
  8. }


 
Voilà, c'est assez "spirit of the C++" pour vous ?  :)  
 
Sinon, je tenais à dire par rapport au topic que tu as lié, que je suis un fervent opposant au singleton façon GoF : ça marche très mal lors de l'initialisation des variables statiques.

n°839844
lsdYoYo
gravity powered
Posté le 02-09-2004 à 14:12:54  profilanswer
 

Taz a écrit :


c'est complètement pourri ta façon de procéder, c'est source d'erreur
un .h avec les déclarations extern, un .cpp avec l'allocation des variables :o


 :jap: Merci, Taz, apparemment tu serais l'unique personne a maîtriser l'unique technique de codage. Comme s'il en existait qu'une seule. Je parle des techniques et non des personnes. Parce que des personnes qui pensent détenir le savoir unique : désolé mais tu n'est pas le seul. Sans parler de CET exemple précis, simplement quand tu critiques un post - que ce soit de manière négative ou même positive - ça serait pas mal d'expliquer pourquoi.
Maintenant, pour reprendre CET exemple :
- qqu'un pose une question précise et cherche des réponses précises à SON problème.
- il n'est pas forcément très utile de refaire le monde en général et le débat sur les variables globales en particulier
- "c'est source d'erreur un .h avec les déclarations extern". Par curiosité, as-tu déjà parcouru les fichiers .h de ton compilateur ? Curieux, avec mon compilo (C++ Builder) je trouve des centaines de déclarations de variable globales en "extern".
 
Pour Lam's :
T'aurais pas *encore* plus compliqué ?
Où as-tu vu que la structure à allouer était un objet avec un constructeur ?
Quel est le besoin impératif de passer par un "new" ?
Une bonne vieille variable globale ne serait-elle pas plus simple ?
Ok, ok, il y a des risques (quelle façon de procéder n'en a pas ???) avec les globales. La soluce s'appelle : test et debug.

n°839868
Lam's
Profil: bas.
Posté le 02-09-2004 à 14:19:45  profilanswer
 

lsdyoyo a écrit :


Pour Lam's :
T'aurais pas *encore* plus compliqué ?
Où as-tu vu que la structure à allouer était un objet avec un constructeur ?
Quel est le besoin impératif de passer par un "new" ?
Une bonne vieille variable globale ne serait-elle pas plus simple ?
Ok, ok, il y a des risques (quelle façon de procéder n'en a pas ???) avec les globales. La soluce s'appelle : test et debug.


 
Oh, j'aurais pu passer par un template, c'est vrai ;)
 
Nan, plus simplement, le premier bout de code que j'ai posté est ce que j'ai trouvé de plus "efficace" pour mes problèmes de variable globales de manière générale. Une variable globale peut poser beaucoup de problèmes (comme tu le dit, on va pas refaire le débat).  
 
Le deuxième bout de code, c'est plus une moquerie aux "puristes" du C++.
 
Quand au new, c'est pour éviter de passer par les références, qui peuvent souvent être confuses. Pas besoin de constructeur pour ça.
 
Maintenant, la meilleure solution, elle existe : c'est celle que l'on comprend, qui fonctionne, et qui demande le moins de temps à implémenter et à maintenir. Donc à chaque développeur ses petites habitudes...
 
Voilà, pas besoin de se facher...

n°839875
lsdYoYo
gravity powered
Posté le 02-09-2004 à 14:21:11  profilanswer
 

:)

n°839904
Taz
bisounours-codeur
Posté le 02-09-2004 à 14:28:25  profilanswer
 

lsdyoyo > commence par comprendre ce que je dis et arrête de transformer mes propos.

n°839992
lsdYoYo
gravity powered
Posté le 02-09-2004 à 14:47:56  profilanswer
 

Tu voulais peut-être faire :
- Dans le .h : les extern
- Dans un seul des .cpp : les allocations
Pourquoi pas ? Je trouve très bien d'avoir les deux dans un .h : un seul fichier à modifier/vérifier.
En quoi est-ce "pourri" ?


Message édité par lsdYoYo le 02-09-2004 à 14:48:24
n°841918
Taz
bisounours-codeur
Posté le 04-09-2004 à 00:42:22  profilanswer
 

oui, il faut faire comme ça, c'est la matière canonique. pourquoi ? parce qu'en fin de compte, c'est la même chose que tu fais avec ton #define conditionel : la présence de l'allocation dans une seule unité de traduction. Alors entre gérer ça à la main, avec les risques d'erreurs, et se contenter de faire un fichier, y a pas à choisir. sinon n'oublie pas de faire exactement la même chose pour toutes les fonctions, interdis toi les .c (allez, je te laisse le main).

n°842183
Panini
Posté le 04-09-2004 à 15:05:44  profilanswer
 

Taz a écrit :

1. init.h
   2. .../...
   3. #ifdef ALLOC_GLOBAL
   4. int toto;
   5. int tata = 93893;     //Avec une valeur de départ  
   6. MaStruct titi;
   7. #else
   8. extern int toto;
   9. extern int tata;      //!!! Ne pas redonner de valeur avec "extern"
  10. extern MaStruct titi;
  11. #endif
 
 
 
c'est complètement pourri ta façon de procéder, c'est source d'erreur
 
un .h avec les déclarations extern, un .cpp avec l'allocation des variables :o


 
A la limite, il peut définir les valeurs dans le .h, mais dans ce cas, il faut les définir en constantes :
const int tata = 93893;  
Ne pas oublier de proteger le fichier contre l'inclusion multiple aussi, des fois que, dans un sursaut d'étourderie ...

n°842189
Taz
bisounours-codeur
Posté le 04-09-2004 à 15:29:06  profilanswer
 

ouais c'est que je dis, c'est source d'erreur ce truc, ça fait 20 ans qu'on fait un .h et un .c on va se faire chier à faire une méthode qui est dangereuse

n°1054925
ben63
Posté le 21-04-2005 à 11:05:24  profilanswer
 

lsdYoYo a écrit :

+1

Code :
  1. init.h
  2. .../...
  3. #ifdef ALLOC_GLOBAL
  4. int toto;
  5. int tata = 93893;     //Avec une valeur de départ  
  6. MaStruct titi;
  7. #else
  8. extern int toto;
  9. extern int tata;      //!!! Ne pas redonner de valeur avec "extern"
  10. extern MaStruct titi;
  11. #endif


 

Code :
  1. <autres modules cpp>
  2. //pas de #define ALLOC_GLOBAL avant #include "init.h"
  3. #include "init.h"
  4. .../...


 


 
Je confirme les propos de Taz quant à dire que c'est source d'erreurs ; par exemple lorsqu'on compile son programme "bout par bout".
Je m'explique : pour les gens qui utilisent  visual sans vouloir se faire chier avec les makefile (j'en fait parti :-D), voilà une situation foireuse :
2 fichiers .cpp incluent init.h
si à la compilation le premier compile bien, le 2eme foire, quand on va recompiler, il ne recompilera pas le 1er (qui a "en lui" la variable globale de créée) et va en recréer une pour le second, la macro ALLOC_GLOBAL étant "nouvelle"
 
Maintenant il me manque surement des connaissances de configuration de visual...

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  variable globale, problème de link

 

Sujets relatifs
organisation de block "div" avec les CSS: problemeprobleme afficahge page web
Problème d'affichage cssprobleme client attente d'une connexion server
[PHP/dédié] Problème de mail ( expediteur = nobody@monserveur.com )Problème avec Rowspan
Problème liste déroulante + javascriptProbleme HTML entre IE et Mozilla
problème pour connection a une bd depuis phppetit problème
Plus de sujets relatifs à : variable globale, problème de link


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR