IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Problème de portée de variable globale


Sujet :

C

  1. #1
    Membre à l'essai
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Points : 15
    Points
    15
    Par défaut Problème de portée de variable globale
    Bonjour à toute la communauté,

    je viens vous voir car je sèche sur un problème que je dois résoudre rapidement (travail de maintenance sur une appli en prod).

    Il s'agit apparemment d'un problème de portée de variable.
    1 - J'ai un binaire dont le source est EcrireJournal.c
    2 - Ce binaire fait appel à une fonction OuvrirLogProd situé dans le source Log.c
    3 - La fonction OuvrirLogProd initialise une variable globale gMess (déclarée dans Log.c donc)
    4 - Le binaire EcrireJournal fait ensuite appel à plusieurs fonctions situées dans le source Oracle.pc
    5 - Une des fonctions du source Oracle.pc fait appel à une fonction LoggerProd (Log.c). Cette fonction utilise la variable globale gMess, qui normalement devrait toujours contenir une valeur, mais elle est vide. Elle devrait pourtant contenir la valeur initialisée au point 3, non ?

    Quel est le prblm ?

    Cdt.

  2. #2
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Bonjour et bienvenue sur les forums de Developpez

    Ah, les variables globales ! Qui écrit dedans ???
    - Elle est censée avoir été initialisée au point 3 à quelle valeur ?
    - L'a t-elle été à la valeur supposée ?
    - Quelle valeur a-telle au point 5 ?

  3. #3
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Et surtout : Es-tu sûr que la variable globale est déclarée correctement et que c'est bien la même variable dans les deux fonctions ? (Afficher l'adresse de la variable peut aider à déboguer).

  4. #4
    Membre à l'essai
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Points : 15
    Points
    15
    Par défaut
    Au point 3, la variable gMess est initialisée avec une chaine de caractère (chemin d'un fichier de conf).

    Au point 5, j'ai fais un printf %s de la variable pour vérifier ce qu'elle contenait : rien.

    J'ai vérifié avec un grep sur tous les sources, rien d'autre ne modifie cette variable.

    Je vais regarder l'adresse, histoire d'être sûr effectivement que je suis toujours sur la même variables !

    -> Ben l'adresse mémoire est la même. On a à faire à la même variable, mais elle perd son contenu !!!

    Ca peut être ennuyant si tous ces sources sont compilés via plusieurs makefile différents ?
    - le binaire EcrireJournal -> 1 makefile
    - le source oracle.pc -> 1 makefile (cela crée une librairie)
    - le source Log.c -> 1 makefile (cela crée une librairie)

  5. #5
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    et gMess est déclarée comment ?

  6. #6
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 949
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 949
    Points : 5 663
    Points
    5 663
    Par défaut
    Gio,

    Et vive les variables globales !!!!

  7. #7
    Membre à l'essai
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Points : 15
    Points
    15
    Par défaut
    gMess est déclaré dans Log.c comme une variable globale (en dehors de toutes fonctions donc).

    En fait, pour schématisé on a :

    Un source A qui fait appel à une fonction d'une source B
    La fonction du source B initialise une variable globale (de B)
    Le source A fait appel ensuite à une fonction d'une source C
    Cette fonction du source C fait appel à une fonction du source B qui exploite la dite variable globale (de B).

    Apparemment, le prblm vient du fait que je passe par le source C. De là, on perd la visibilité sur la fameuse variable globale.

    Pourtant, sur la même appli, cette façon de procédé a déjà été employée et fonctionne ...

  8. #8
    Membre à l'essai
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Points : 15
    Points
    15
    Par défaut
    Citation Envoyé par droggo Voir le message
    Et vive les variables globales !!!!
    Je suis d'accord avec toi, c'est vraiment pourri.

  9. #9
    Membre à l'essai
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Points : 15
    Points
    15
    Par défaut
    Je commence à cerner le prblm.

    En repartant du précédent schéma, j'ai l'impression que le fait que le source B soit compilé dans une librairie à part pose prblm.

    Si le source B était inclu au source A, donc compilé avec A pour donner un binaire unique, je pense que je n'aurais plus de prblm.

    Donc je suis dans une impasse.

    la poisse ... !

  10. #10
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Un source A qui fait appel à une fonction d'une source B
    La fonction du source B initialise une variable globale (de B)
    Le source A fait appel ensuite à une fonction d'une source C
    Cette fonction du source C fait appel à une fonction du source B qui exploite la dite variable globale (de B).
    D'après ce que tu dis, la variable globale définie dans B n'est modifiée que dans B. Il ne devrait pas y avoir de problèmes
    De là, on perd la visibilité sur la fameuse variable globale
    le compilateur ou le linker le dirait dans ce cas.
    Quel est le type de gMess ?

  11. #11
    Membre à l'essai
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Points : 15
    Points
    15
    Par défaut
    Citation Envoyé par diogene Voir le message
    le compilateur ou le linker le dirait dans ce cas.
    Quel est le type de gMess ?
    gMess est un pointeur de type char

  12. #12
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Au point 3, la chaîne de caractères est-elle allouée de façon dynamique, et la chaîne (chemin d'un fichier de conf) copiée dans ce tableau ?
    Au point 5 gMess est-il égal à NULL ?

  13. #13
    Membre à l'essai
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Points : 15
    Points
    15
    Par défaut
    Citation Envoyé par diogene Voir le message
    Au point 3, la chaîne de caractères est-elle allouée de façon dynamique, et la chaîne (chemin d'un fichier de conf) copiée dans ce tableau ?
    Au point 5 gMess est-il égal à NULL ?
    Au point 3 le pointeur est initialisé comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    long OuvrirLogProd(char *pFichier, ...)
    {
       gMess = pFichier;
       ...
    })
    Au point 5, gMess est null, il contient '\0'.

  14. #14
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Au point 5, gMess est null, il contient '\0'.
    Entends-tu par là que gMess ==0 ou que *gMess =='\0'

    Dans le dernier cas il n'est pas NULL. Il pointe sur une chaîne vide. Es-tu sur que la chaîne (chemin d'un fichier de conf) passée en argument est toujours valide. Comme tu ne copies pas la chaîne mais seulement l'adresse de la chaîne, si cette chaîne a été détruite entre temps, sa place mémoire a été récupérée et peut avoir été utilisée par le compilateur pour autre chose. C'est certain si elle est en allocation automatique ou en allocation dynamique suivi d'un free entre les points 3 et 5.
    Une simple copie de pointeur me semble bien imprudente ou alors il faut bien contrôler la durée de vie de la chaîne.

    Dans le premier cas, comme avant le point 3 il devait déjà y avoir NULL, il faut vérifier si l'initialisation du point 3 est bonne. Si c'est le cas, comme l'adresse mémoire semble la même aux points 3 et 5, il faut peut être envisager une destruction par dépassement lors de l'écriture sur une autre variable.

  15. #15
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 916
    Points
    17 916
    Billets dans le blog
    2
    Par défaut
    comme dit diogene, si la chaine passée en paramètre est locale, ou a une durée de vie "courte" par rapport au cycle du ré-appel, à ce compte-là ce n'est pas une copie de pointeur qu'il faudrait faire, mais du contenu...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    long OuvrirLogProd(char *pFichier, ...)
    {
       gMess = strdup(pFichier);
       ...
    }

  16. #16
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par draudrau Voir le message
    je viens vous voir car je sèche sur un problème que je dois résoudre rapidement (travail de maintenance sur une appli en prod).

    Il s'agit apparemment d'un problème de portée de variable.
    1 - J'ai un binaire dont le source est EcrireJournal.c
    2 - Ce binaire fait appel à une fonction OuvrirLogProd situé dans le source Log.c
    3 - La fonction OuvrirLogProd initialise une variable globale gMess (déclarée dans Log.c donc)
    Il est d'usage d'éviter les variables globales (les paramètres des fonctions et des les structures permettent de les éviter).

    Mais si tu y tiens, vérifie que les conditions d'utilisation sont respectées :

    http://emmanuel-delahaye.developpez....s.htm#globales

  17. #17
    Membre à l'essai
    Inscrit en
    Novembre 2007
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 23
    Points : 15
    Points
    15
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    comme dit diogene, si la chaine passée en paramètre est locale, ou a une durée de vie "courte" par rapport au cycle du ré-appel, à ce compte-là ce n'est pas une copie de pointeur qu'il faudrait faire, mais du contenu...
    Bon ben c'était ça.
    La chaine passée en paramètre est issus d'une variable locale à la fonction main.
    J'ai sorti la variable du main et ça fonctionne.

    C'est con mais j'ai parcouru une centaine de fois ce code source et j'ai raté ça.

    Quand à la façon dont cette appli est codée, c'est clair qu'il y a plein de choses à revoir.
    Mais je ne suis pas là pour ça.
    Ce sont toujours les même contraintes : c'est en prod, ça fonctionne, on ne va pas tout refaire (le porte-monaie n'apprécierait pas !)

    Merci à tous !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Mail] problème de portée de variables
    Par xclam dans le forum Langage
    Réponses: 2
    Dernier message: 12/04/2007, 09h35
  2. Problème de Portée de Variable
    Par Julien_C++ dans le forum C++
    Réponses: 7
    Dernier message: 18/09/2006, 10h13
  3. portée des variables globales dans un fichier js
    Par crakazoid dans le forum Général JavaScript
    Réponses: 19
    Dernier message: 14/04/2006, 16h49
  4. [VBA-E] Problème de portée de variable [débutant]
    Par vivelesgnous dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 01/03/2006, 18h28
  5. [XSL]Problème de portée des variables
    Par djulesp dans le forum XSL/XSLT/XPATH
    Réponses: 6
    Dernier message: 17/09/2004, 10h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo