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 :

Rendre une structure non copiable


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2008
    Messages
    187
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Octobre 2008
    Messages : 187
    Points : 448
    Points
    448
    Par défaut Rendre une structure non copiable
    Bonjour,

    est-il possible d'empêcher une structure d'être copiable en C99 ? Mon problème est que j'ai une structure basique de tableau dynamique qui ressemble à ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    struct DynamicArray
    {
        int size;
        int capacity;
        size_t eltsize;
        void* data;
    }
     
    void DynamicArray_Init(struct DynamicArray* array, size_t eltSize);
    void DynamicArray_Add(struct DynamicArray* array, void* value);
    et que si quelqu'un a le malheur d'écrire plus tard:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct DynamicArray arrayA;
    DynamicArray_Init(&arrayA, sizeof(int));
     
    int i = 3;
    struct DynamicArray arrayB = arrayA;
    DynamicArray_Add(&arrayB, &i);
    Alors dans ce cas là, il se peut que la structure A soir invalidée à cause des opérations de realloc potentielles dans le Add.

    J'imagine que la seule solution est de rendre la structure opaque, mais c'est un peu dommage vu que du coup ça n'est plus possible de l'allouer de manière automatique -_-

    Merci d'avance.

  2. #2
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Loa,

    Ta structure s'adresse à des programmeurs suffisamment formés, à eux de prendre leurs responsabilités.
    Si les cons volaient, il ferait nuit à midi.

  3. #3
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 580
    Points
    218 580
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Vous pouvez faire en sorte que la structure devienne opaque (que le programmeur ne connaisse jamais son contenu réel). Pour cela, il ne faut jamais lui donné le .h où la structure est déclarée et lui donner assez de fonctions pour "jouer" avec la structure.
    Lorsqu'il a besoin de l'utiliser, il l'utilise seulement à travers des pointeurs et pour sa déclaration, il utilise un bête :
    indiquant que le symbole existe bien, mais que bon, on ne sait pas ce que c'est. Beaucoup de bibliothèque agissent ainsi (SDL 2, libcg, ...)
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Et même la bibliothèque standard, avec les FILE* de fopen, fclose, fread etc
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  5. #5
    Membre averti
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2008
    Messages
    187
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Octobre 2008
    Messages : 187
    Points : 448
    Points
    448
    Par défaut
    Citation Envoyé par droggo Voir le message
    Ta structure s'adresse à des programmeurs suffisamment formés, à eux de prendre leurs responsabilités.
    Certes, mais on est jamais à l'abri d'une inattention

    Citation Envoyé par LittleWhite Voir le message
    Vous pouvez faire en sorte que la structure devienne opaque
    Oui c'est ce que je disais, mais je trouve dommage de devoir utiliser ce mécanisme et perdre en même temps la possibilité d'allouer un tableau dynamique sur la pile, mais bon je n'ai pas trop le choix on dirait !

    Sinon je viens d'avoir une idée, qui consisterait à vérifier les erreurs au runtime. Dans le header :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct DynamicArray
    {
        int size;
        int capacity;
        size_t eltsize;
        void* data;
        int signature;
    }
     
    void DynamicArray_Init(struct DynamicArray* array, size_t eltSize);
    void DynamicArray_Add(struct DynamicArray* array, void* value);
    et dans le .c :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void DynamicArray_Init(struct DynamicArray* array, size_t eltSize)
    {
        array->signature = (int) array;
        ...
    }
     
    void DynamicArray_Add(struct DynamicArray* array, void* value)
    {
        assert(array->signature == (int) array);
        ...
    }
    ainsi si un programmeur a le malheur d'assigner un tableau directement, la signature ne sera plus bonne et on aura un assert au runtime.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct DynamicArray arrayA;
    DynamicArray_Init(&arrayA, sizeof(int));
     
    int i = 3;
    struct DynamicArray arrayB = arrayA;
    DynamicArray_Add(&arrayB, &i);    // assert ici car arrayB.signature != &arrayB
    Vous en pensez quoi ?

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 687
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 687
    Points : 30 980
    Points
    30 980
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dancingmad Voir le message
    Sinon je viens d'avoir une idée, qui consisterait à vérifier les erreurs au runtime. Dans le header :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct DynamicArray
    {
        int size;
        int capacity;
        size_t eltsize;
        void* data;
        int signature;
    }
     
    void DynamicArray_Init(struct DynamicArray* array, size_t eltSize);
    void DynamicArray_Add(struct DynamicArray* array, void* value);
    et dans le .c :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void DynamicArray_Init(struct DynamicArray* array, size_t eltSize)
    {
        array->signature = (int) array;
        ...
    }
     
    void DynamicArray_Add(struct DynamicArray* array, void* value)
    {
        assert(array->signature == (int) array);
        ...
    }
    Vous en pensez quoi ?
    Bonjour

    Pourquoi caster systématiquement en int ? Pourquoi ne pas stocker directement l'adresse elle-même ???

    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
    typedef struct s_DynamicArray
    {
        int size;
        int capacity;
        size_t eltsize;
        void* data;
        struct s_DynamicArray *signature;
    } t_DynamicArray;
     
    void DynamicArray_Init(t_DynamicArray* array, size_t eltSize)
    {
        array->signature = array;
        ...
    }
     
    void DynamicArray_Add(t_DynamicArray* array, void* value)
    {
        assert(array->signature == array);
        ...
    }
    ...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonsoir,

    Et pourquoi ne pas empêcher de pointer vers l'adresse fournie pour la structure de données ? Ça reviendrait plus ou moins à empêcher toute copie de données à une adresse précise, seule la structure de données ayant cette adresse peut manipuler les données qui s'y trouvent.

    C'est juste une idée loufoque.
    À bientôt.
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  8. #8
    Membre averti
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2008
    Messages
    187
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Octobre 2008
    Messages : 187
    Points : 448
    Points
    448
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Pourquoi caster systématiquement en int ? Pourquoi ne pas stocker directement l'adresse elle-même ???
    Ah euh oui en effet c'est plus logique ^^

    Citation Envoyé par sambia39 Voir le message
    Et pourquoi ne pas empêcher de pointer vers l'adresse fournie pour la structure de données ?
    Je suis pas sûr de comprendre ce que tu veux dire sambia39, tu parle d'empêcher de créer la structure directement et renvoyer une sorte de 'handle' ? A creuser, mais est-ce que ça ne revient pas à rendre la structure opaque ?

    Bon sinon je crois que j'ai la réponse à ma question. Merci bien !

  9. #9
    Invité
    Invité(e)
    Par défaut
    hello,

    le plus simple pourqu'il fasse pas n'importe quoi c'est de pas lui montrer le contenu de ta structure.

    l'utilisateur utilise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    struct DynamicArray* arr = malib_allocate(10); //tableau de taille 10
    malib_delete(arr);
    si comme un trufion il écrit
    struct DynamicArray* arr2 = arr, tu peux rien faire contre ca.
    et j'ai meme envie de dire que c'est bien fait si après ca lui pète au nez.
    mais bon, s'il copie un pointeur c'est ptet juste pour renommer sa variable.
    (typiquement sil a un truc style maStructureA.maStructureB.arr, ben il veut écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    struct DynamicArray* arr2 = maStructureA.maStructureB.arr;
    ce qui lui fait un alias)

    dans ta lib tu as le .h auquel l'utilisateur a accès:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    struct Bob;
    void malib_allocate(int);
    void malib_delete(struct Bob*);
    et dans le .c:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #include "Bob.h"
    struct Bob{
     int everything;
    };
    struct Bob* malib_allocate(int size){}
    void malib_delete(struct Bob* bob){}
    effectivement tu te tapes l'alloc sur le Dynamic array, mais au moins l'utilisateur sait explicitement qu'il copie du pointeur, et en plus tu peux modifier ta struct comme tu le souhaites, de toute façon l'utilisateur n'en a pas connaissance!

  10. #10
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonsoir
    Par mon idée, je voulais dire, empêcher tout pointage direct vers l'adresse de la structure mais, techniquement c'est impossible donc, et ça je ne lés pas dit dans mon dernier poste,
    tu n'a pas d'autre solution que de passer par la POA c'est-à-dire de la programmation orienté aspect ou un hyperviseur en résumé, un contrôleur d'accès qui décidera si oui ou non ta variable ou structure à un accés ou autre.
    ce sont les seules méthodes qui te permet de faire ce dont tu a besoin
    à bientôt
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  11. #11
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Si tu veux supprimer le pointage direct, il faut ruser, comme le fait opengl (ou faisait, mon souvenir est ancien)

    une fonction create_bidule(...) retourne un identifiant (entier), qui sera utilisé à la place du pointeur dans l'interface de la bibliothèque.
    Ca sous entend un tableau interne (global ou dans un contexte) qui permet la traduction.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  12. #12
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonjour
    Bien comme idée et ça confirme ce que j'ai énoncé au début c'est de la programmation orienté aspect donc, au final pour le besoin de son application il n'aura pas d'autres choix de faire soit de la programmation orienté aspect ou un hyperviseur
    à bientôt.
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  13. #13
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Bof, de grands mots pour pas grand chose.

    Il suffit d'avoir deux fonctions:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int createBidule(int a, int b);
    void destroyBidule(int id);
    et une fonction privée, absente de l'en-tête.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Bidule* BiduleOf(int id);
    Bien sûr, cela veut aussi dire qu'il y a (dans cette version) une variable globale de type tableau (ou autre) permettant de stocker les correspondances identifiant -> pointeur
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  14. #14
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonsoir de bien gros mots ? l'exemple que vous avez posté ce n'est pas de la POA à tout hasard ?
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  15. #15
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Aucune idée.
    C'est de l'abstraction de base, en général on appelle ça un handle (si on veut parler en design pattern).

    Dans mon idée, la POA devrait s'axer sur des aspects, tels que iterable, affectable, comparable, etc.
    Cela dit, je n'ai jamais étudié la POA.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

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

Discussions similaires

  1. Rendre une ComboBox non éditable
    Par Tangui dans le forum Débuter
    Réponses: 1
    Dernier message: 08/05/2008, 16h22
  2. Rendre une fenêtre non-redimensionnable
    Par TSalm dans le forum Windows
    Réponses: 10
    Dernier message: 15/11/2007, 10h57
  3. Rendre une Page non valide
    Par miniseb dans le forum ASP.NET
    Réponses: 1
    Dernier message: 21/08/2007, 11h14
  4. Réponses: 2
    Dernier message: 16/03/2007, 09h13

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