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 :

les variables globales peuvent provoquer des erreurs ?


Sujet :

C

  1. #1
    Membre du Club
    Inscrit en
    Mai 2009
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 62
    Points : 43
    Points
    43
    Par défaut les variables globales peuvent provoquer des erreurs ?
    Bonjour,

    Dans mon projet personnel, je développe un petit moteur 2D/3D, pour cela je développe différentes DLL je m'explique:
    par exemple le fichier Core.dll contient des fonctions sur les listes chaînées, les piles,table de hashage, des fonctions manipulations des matrices, bref pas mal de choses, il m'arrive parfois d'utiliser des variables globales, par exemple pour le cas de la pile des matrices(comme sur openGL) voici un exemple du fichier
    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
     
     
    static MatrixStack projection;
    static MatrixStack modelview;
    static MatrixStack* current_stack;
     
    .......
     
    void CORE_API  MatrixInit(void)
    {
        Matrix4 identity;
     
        Matrix4SetIdentity(&identity);
     
        MatrixStackInit(&projection);
        MatrixStackInit(&modelview);
     
        MatrixStackPush(&projection,&identity);
        MatrixStackPush(&projection,&identity);
        MatrixStackPush(&modelview,&identity);
        MatrixStackPush(&modelview,&identity);
        current_stack=&modelview;
     
    }
    void CORE_API MatrixMode(ENUM_MATRIX_TYPE mode)
    {
     
        switch(mode)
        {
        case EMT_MODELVIEW:
            current_stack = &modelview;
            break;
        case EMT_PROJECTION:
            current_stack = &projection;
            break;
     
        default:
            break;
        }
    }
     
    etc ....
    Donc le problème se pose lorsque j'utilise les différents DLL, j'ai des segfault non pas a cause d'un malloc ou d'un free.
    Lorsque je debug mon programme(j'utilise codeblocks) quand je je "watch" mes variable je remarque les valeurs changent toutes seules en executant le debugage en mode pas à pas.

    Donc voila je voudrais savoir est ce que les variables globales provoquent ce genre de problème et est ce qu'il y a une autre alternatif pour éviter les variables globals voila merci d'avance

  2. #2
    Membre habitué
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 81
    Points : 128
    Points
    128
    Par défaut
    Les variables globales peuvent être modifiées si plusieurs threads accèdent à ses variables sans qu'elles soient protégées (par un mutex).

  3. #3
    Membre du Club
    Inscrit en
    Mai 2009
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 62
    Points : 43
    Points
    43
    Par défaut
    Pour le moment je n'utilise pas de thread

  4. #4
    Membre émérite
    Avatar de TheGzD
    Homme Profil pro
    Ingénieur/ Docteur en Informatique
    Inscrit en
    Avril 2007
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Ingénieur/ Docteur en Informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 1 327
    Points : 2 677
    Points
    2 677
    Par défaut
    Les problèmes que tu décris sentent quand même très fortement les threads ... les DLL pourraient très bien en instancier sans que tu le saches. Ton mode debug ne stopant que le thread exécutant le code que tu suis pas-à-pas tu peux obtenir des comportements erratiques de ce style (problème de synchro, accès concurrent du débuggueur, ...).

    Il va falloir que tu lâches un peu plus de code et/ou d’explications comme par exemple concernant l'implémentation de tes DLL ainsi que la façon dont tu les charges dans ton programme "principal".
    Vous postez du code ? Merci d'utiliser les balises
    Un message vous paraît pertinent ? Merci de le gratifier d'un vote positif
    Vous avez obtenu une réponse à votre question ? Merci d'utiliser le tag
    __________________
    Ingénieur R&D, diplômé en 2007 de l'ISIMA
    Docteur en informatique, diplômé en 2015 de l'EDSPI de Clermont-Ferrand

  5. #5
    Membre du Club
    Inscrit en
    Mai 2009
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 62
    Points : 43
    Points
    43
    Par défaut
    Bon ok
    Pour créer une lib DLL je crée un projet codeblocks( dynamic library ), ensuite j'ajoute un fichier .h contenant un truc comme ça pour exporter mes fonctions..
    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
     
    #ifndef __HEADER_H__
    #define __HEADER_H__
     
    #ifdef WIN32
     
    #ifdef MPGE_CORE_EXPORTS
     
       #define MPGE_CORE_API __declspec(dllexport)
     
    #else
     
       #define MPGE_CORE_API __declspec(dllimport)
     
    #endif 
     
    #endif /* WIN32 */
    Voici un exemple d'une structure buffer:
    le fichier buffer.c
    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
     
    #include "MPGE_Buffer.h"
    #include "MPGE_Memory.h"
     
    MPGEBuffer MPGE_CORE_API MPGE_BufferNew(u32 size)
    {
        MPGEBuffer buffer;
     
        buffer=MPGE_MemoryAlloc(sizeof(_Buffer));
        if(buffer)
        {
            buffer->data=MPGE_MemoryAlloc(size);
            if(buffer->data)
            {
                buffer->size=size;
                return buffer;
            }
            else
                MPGE_MemoryFree(buffer);
     
        }
     
            return null;
    }
    void MPGE_CORE_API MPGE_BufferDelete(MPGEBuffer buffer)
    {
        MPGE_MemoryFree(buffer->data);
        MPGE_MemoryFree(buffer);
    }
    void MPGE_CORE_API MPGE_BufferSetData(MPGEBuffer buffer,void* data)
    {
        MPGE_MemoryCopy(buffer->data,data,buffer->size);
    }
    void* MPGE_CORE_API MPGE_BufferGetData(const MPGEBuffer buffer)
    {
        return buffer->data;
    }
    const void* MPGE_CORE_API MPGE_BufferGetConstData(const MPGEBuffer buffer)
    {
        return buffer->data;
    }
    le fichier buffer.h
    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
     
     
    #include "MPGE_CoreConfig.h"
    #include "MPGE_Types.h"
     
    typedef struct _Buffer
    {
        void* data;
        u32 size;
    }_Buffer;
     
    typedef _Buffer* MPGEBuffer;
     
    MPGEBuffer MPGE_CORE_API MPGE_BufferNew(u32 size);
    void MPGE_CORE_API MPGE_BufferDelete(MPGEBuffer buffer);
    void MPGE_CORE_API MPGE_BufferSetData(MPGEBuffer buffer,void* data);
    void* MPGE_CORE_API MPGE_BufferGetData(const MPGEBuffer buffer);
    const void* MPGE_CORE_API MPGE_BufferGetConstData(const MPGEBuffer buffer);
    je fais comme ceci pour les autres fonctions, je clique sur play et codeblocks me génére un fichier .a et un fichier .dll.
    ensuite je copie les headers de mon projet dans le dossier include de codblocks et le fichier .a dans le dossier lib de codblocks.
    Quand je veux utiliser ma DLL je crée un autre projet C j'inclue les fichiers .h nécessaires et je link avec le fichier .a, quand je compile je copie le fichier .DLL a coté de mon exécutable et c'est tout.
    C'est la démarche que je suis

  6. #6
    Membre habitué
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 81
    Points : 128
    Points
    128
    Par défaut
    Ta démarche permet de lier statiquement tes DLL à tes programmes mais je ne pense pas que tes problèmes de globales viennent de là.
    Je ne vois pas trop ce qui pourrait faire changer tes variables hormis des accès concurrents (donc threads).

    Citation Envoyé par manrugby Voir le message
    Est ce qu'il y a une autre alternatif pour éviter les variables globales
    Tout dépend de l'intérêt de la globale (qui peut être justifiée) mais tu peux créer des fonctions d'initialisation/destruction dans tes DLL qui retournent un objet opaque que l'appelant stocke et utilise par la suite pour tous les appels à la DLL.
    Comme un pointeur this en C++.

  7. #7
    Membre du Club
    Inscrit en
    Mai 2009
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 62
    Points : 43
    Points
    43
    Par défaut
    Je ne te suis pas ....
    Je ne comprend pas ce que tu veux dire par la
    mais tu peux créer des fonctions d'initialisation/destruction dans tes DLL qui retournent un objet opaque que l'appelant stocke et utilise par la suite pour tous les appels à la DLL.

  8. #8
    Membre habitué
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 81
    Points : 128
    Points
    128
    Par défaut
    Ce que je disais correspond exactement à la manière dont tu gères tes buffers : tu encapsules toutes les données dans une structure _Buffer et l'appelant manipule un objet MPGEBuffer.

    Je pense qu'il faut que tu fasses pareil avec tes variables globales qui posent problème. Il faut que tu les encapsules.

  9. #9
    Membre du Club
    Inscrit en
    Mai 2009
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 62
    Points : 43
    Points
    43
    Par défaut
    Oui je comprend mieux maintenant.
    J'ai une autre théorie, le problème que j'ai cité est déjà survenue dans un autre projet, (voir le code ci-dessous) un tableau déclaré globalement et dans le main plusieurs variables, j'avais souvent la même erreur, les valeurs des variables changent toutes seules notamment leurs adresses suites à la modification d'une autre variable qui n'a aucun lien avec ces derniers,peut être un dépassement de la taille maximale de la pile ou sont stocké les variable en mémoire à l’exécution du programme ?

    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
     
    #include <stdio.h>
    #include <stdlib.h>
     
    int tab[10][100]; 
     
    int main()
    {
      int p*;
      char tab1[200];
     
      float x;
      double *y;
     
    /* .......*/
     
    /* par exemple si je modifie le tableau  tab*/
    memcpy(&tab[2][0],p,sizeof(int)*50);
    /* sachant bien sur que p a été alloué dynamiquement et que le pointeur n'est pas null, quand je debug je m'apercoi que tab1 pointe sur une autre adresse, la variable x a changé d'adresse elle pointe sur une autre zone... */
    }
    Merci encore
    EDIT:
    j'ai oublier d’évoquer un autre truc sur les variables globales:

    J'utilise une structure CoreVersion qui me permettra de savoir quel est la version du fichier dll voici le code:

    fichier .c
    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
     
    #include "MPGE_CoreVersion.h"
     
    static _CoreVersion version = {MPGE_ECV_MAJOR,MPGE_ECV_MINOR,MPGE_ECV_PATCH};
     
    const MPGECoreVersion* MPGE_CORE_API MPGE_CoreGetVersion(void)
    {
        return &version;
    }
     
    u16 MPGE_CORE_API MPGE_CoreGetMajor(const MPGECoreVersion* version)
    {
        return version->major;
    }
    u16 MPGE_CORE_API MPGE_CoreGetMinor(const MPGECoreVersion* version)
    {
        return version->minor;
    }
    u16 MPGE_CORE_API MPGE_CoreGetPatch(const MPGECoreVersion* version)
    {
        return version->patch;
    }
    fichier .h
    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
     
    #ifndef __MPGE_CORE_VERSION_H__
    #define __MPGE_CORE_VERSION_H__
     
    #include "MPGE_CoreConfig.h"
    #include "MPGE_Types.h"
     
    typedef enum MPGE_ENUM_CORE_VERSION
    {
        MPGE_ECV_MAJOR = 0,
        MPGE_ECV_MINOR = 1,
        MPGE_ECV_PATCH = 0
    }MPGE_ENUM_CORE_VERSION;
     
    typedef struct _CoreVersion
    {
        u16 major;
        u16 minor;
        u16 patch;
    }_CoreVersion;
     
    typedef _CoreVersion MPGECoreVersion;
     
    const MPGECoreVersion* MPGE_CORE_API MPGE_CoreGetVersion(void);
     
    u16 MPGE_CORE_API MPGE_CoreGetPatch(const MPGECoreVersion* version);
    u16 MPGE_CORE_API MPGE_CoreGetMinor(const MPGECoreVersion* version);
    u16 MPGE_CORE_API MPGE_CoreGetMajor(const MPGECoreVersion* version);
    #endif
    est-ce la bonne manière de faire ou il y a une autre façon ?

Discussions similaires

  1. Les variables globales en C++
    Par jeje99 dans le forum C++
    Réponses: 4
    Dernier message: 03/02/2006, 15h52
  2. Réponses: 13
    Dernier message: 21/11/2005, 11h05
  3. Supprimer la mémoire utilisée par les variables globales
    Par dnaprotector dans le forum OpenGL
    Réponses: 4
    Dernier message: 21/07/2005, 13h18
  4. question sur les variables globales et les thread posix
    Par souris_sonic dans le forum POSIX
    Réponses: 5
    Dernier message: 13/06/2003, 13h59
  5. les variables globales static
    Par gRRosminet dans le forum C
    Réponses: 8
    Dernier message: 27/04/2002, 08h34

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