Forum Programmation.c problème de struct et d'alignement

Posté par  .
Étiquettes : aucune
0
4
jan.
2007
Dans ce petit programme, j'ai une erreur étrange (pour moi):


#include <stdio.h>;

typedef struct {
int row;
int col;
} *Pos;

typedef struct {
char* t;
int a;
int b;
int c;
Pos cur;
} *Doc;

int main(int argc, char *argv[])
{
Doc doc = malloc(sizeof(Doc));
Pos cur = malloc(sizeof(Pos));

cur->;row = 1;
doc->cur = cur;

printf("val: %d", doc->;cur->;row);
return 0;
}


Me donne:
% gcc test.c && ./a.out
val: 134520856

Si je supprimme a, b ou c de la struc, le résultat correct de 1 revient. J'aimerais comprendre pourquoi ce problème arrive (alignement ?) et qu'est ce que je fais de faux dans mon code.

Voili, merci d'avance.

PS: désolé pour les caractères plus grand et plus petit apparaissant faux, je n'arrive pas à les faire sortir justes...
  • # les ;

    Posté par  . Évalué à 1.

    Question peut-être bête, mais c'est normal tous ces ";" ?
  • # Type struct != type pointeur

    Posté par  . Évalué à 4.

    Tu a définis Doc et Pos directement comme étant des types "pointeur vers structure" au lieu "structure"; tes deux malloc utilisent donc le sizeof de ces pointeurs (soit 4 octets sur une machine 32 bits) au lieu de la taille réelle des structures.
    Tes deux variables "doc" et "cur" vont donc se retrouver allouées dans la ram avec une taille de 4 octets alors qu'elles en ont besoin de plus, et les acces de leurs champs vont alors déborder. Par exemple là, quand tu écris la valeur de doc->cur, tu vas en fait taper pile à l'emplacement mémoire de cur->row :)

    Tu pourrais corriger rapidement avec "malloc(sizeof(&Doc))" pour avoir la taille réellement nécessaire; mais je trouve que ça fait beaucoup de circonvolutions et que ça embrouille le cerveau.
    Définis plutot tes types de structure en tant que structure ("typedef struct {...} Doc" au lieu de "*Doc") et déclare des variables explicitement pointeurs
    (Doc *doc, Pos *cur;), ce sera plus clair.
    • [^] # Re: Type struct != type pointeur

      Posté par  . Évalué à 3.

      tes deux malloc utilisent donc le sizeof de ces pointeurs (soit 4 octets sur une machine 32 bits)
      La taille d'un pointeur n'est pas forcément 4 octets, même si c'est usuel sur les architectures 32 bits (au regard de la norme C, ça peut être 1, 2, 8, 15...).
      Tu pourrais corriger rapidement avec "malloc(sizeof(&Doc))" pour avoir la taille réellement nécessaire; mais je trouve que ça fait beaucoup de circonvolutions et que ça embrouille le cerveau.
      Petite erreur: "*doc". "&Doc" ne compilera pas (on ne peut prendre l'adresse d'un type).
      Définis plutot tes types de structure en tant que structure ("typedef struct {...} Doc" au lieu de "*Doc") et déclare des variables explicitement pointeurs
      (Doc *doc, Pos *cur;), ce sera plus clair.
      C'est une question de style (voir mon autre post plus bas)...
    • [^] # Re: Type struct != type pointeur

      Posté par  . Évalué à 1.

      merci beaucoup, après coup je me sens vraiment bête :-)

      En fait j'avais déjà corrigé mon programme de la manière que tu décris, mais je ne comprenais tjs pas pourquoi cela ne marchait pas avant. Et évidemment je voulais comprendre.
  • # Erreur de typage et malloc

    Posté par  . Évalué à 3.

    #include <stdio.h>;
    Le point-virgule est en trop.
    typedef struct {
        int row;
        int col;
    } *Pos;
    Tu définis le type Pos comme pointeur sur une structure anonyme (on va dire "aPos").
    typedef struct {
        /*...*/
    } *Doc;
    Idem pour Doc.
    int main(int argc, char *argv[])
    {
        Doc doc = malloc(sizeof(Doc));
        Pos cur = malloc(sizeof(Pos));
    
    Deux erreurs :
    1. Il faut vérifier le retour de *alloc ;
    2. sizeof(Doc) retourne la taille du type Doc, i.e. pointeur sur la structure anonyme "aDoc". Or, ce que tu veux, c'est allouer un espace mémoire suffisant pour une structure "aDoc".
    Il fallait donc faire soit (code non testé) :
    typedef struct {
        int row;
        int col;
    } aPos;
    
    typedef aPos *Pos;
    
    /*...*/
        Pos cur = malloc(sizeof(aPos));
    Mais cette solution demande de redéfinir tes structures de données, donc c'est assez intrusif (peut-être avais-tu une bonne raison pour laisser le type structure anonyme). Il y a donc une autre solution, qui es tà la fois plus simple et plus maintenable :
        Pos cur = malloc(sizeof *cur)
    Avec cette dernière, sizeof *cur détermine la taille correcte, quel que soit le type de cur, ou la manière dont il a été défini (*).
        cur->;row = 1;
    Erreur de syntaxe, ton programme ne devrait même pas compiler (ou alors le point-virgule est arrivé là durant le copié-collé ?).
      (*)Bon, à l'exception d'un type incomplet où la définition de la structure ne serait pas visible.
      • [^] # Re: Erreur de typage et malloc

        Posté par  . Évalué à 1.

        Merci beaucoup pour ces explications.

        Non je n'avais pas de raison de laisser mes structures anonymes, je supposais simplement toujours les utiliser sous forme de pointeurs. Quelle peut etre une bonne raison d'avoir des structures anonymes ?

        Les erreurs de syntaxes proviennent du combat entre moi et l'apperçu de mon post sur linuxfr :-)

    Suivre le flux des commentaires

    Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.