Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Initialisation de structure

15 réponses
Avatar
Tutu
Bien le bonjour,

j'ai un leger soucis pour initialiser correctement une structure.

Voici le code:

typedef struct foo_s {
/* ces trois champs sont de meme longueur LENGHT1 */
char* un;
char* deux;
char* trois;
} foo_t;

typedef foo_t** bar_t;

typdef struct quux_s {
bar_t toto;
int tata;
int tutu;
...
} quux_t;

Je souhaite en fait initialiser une variable de type quux_t,
sachant que "un" "deux" et "trois" sont de longueur N, et que
toto est un tableau a deux dimensions, K et L (les valeurs ne sont
pas connues a la compilation, d'ou les pointeurs...).

j'ai pense a quelque chose dans ce gout-la :

void init_blah(quux_t* q, bar_t k, int i, int j, etc)
{
q->tata = i;
q->tutu = j;
init_bouh(&(k->toto), i, j);
}

et

void init_bouh(bar_t* b, int i; int j)
{
int x, y, z;
*b = malloc(i * sizeof(foo_t*));
for(x=0; x<i; ++x)
{
*b[x] = malloc(j * sizeof(foo_t));
for(y=0; y<j; y++)
{
*b[x][y].un = malloc(LENGTH1);
*b[x][y].deux = malloc(LENGTH1);
*b[x][y].trois = malloc(LENGTH1);
}
}
}

J'ai volontairement omis les verifications de retour de malloc().
Sur ce code, j'ai un segfault des l'allocation d'espace pour "un",
une idee ?


P.

10 réponses

1 2
Avatar
Richard Delorme

void init_bouh(bar_t* b, int i; int j)
{
int x, y, z;
*b = malloc(i * sizeof(foo_t*));
for(x=0; x<i; ++x)
{
*b[x] = malloc(j * sizeof(foo_t));
(*b)[x] = malloc(j * sizeof(foo_t));

for(y=0; y<j; y++)
{
*b[x][y].un = malloc(LENGTH1);
(*b)[x][y].un = malloc(LENGTH1);


J'ai volontairement omis les verifications de retour de malloc().
Sur ce code, j'ai un segfault des l'allocation d'espace pour "un",
une idee ?


Il manque des parenthèses. Les opérateurs postfixés sont prioritaires
sur les opérateurs préfixés, donc *b[x][y] est équivalent à *(b[x][y]),
or tu veux plutôt (*b)[x][y] me semble-t-il.

--
Richard

Avatar
Tutu

Il manque des parenthèses. Les opérateurs postfixés sont prioritaires
sur les opérateurs préfixés, donc *b[x][y] est équivalent à *(b[x][y]),
or tu veux plutôt (*b)[x][y] me semble-t-il.


Tout a fait. J'ai oublie les parentheses parce que j'ai recopie a la main
le code (l'original est bien plus complique, mais je suis certain que c'est
ce qui est presente ici qui est en cause). En plus, je dois preciser que j'ai
dit une une chose a moitie exacte, le probleme "doit" se passer lors de
l'initialisation, parce que quand je tente d'acceder a un champ (exemple a la
fin du code (corrige)), j'ai un segfault :

typedef struct foo_s {
/* ces trois champs sont de meme longueur LENGHT1 */
char* un;
char* deux;
char* trois;
} foo_t;

typedef foo_t** bar_t;

typdef struct quux_s {
bar_t toto;
int tata;
int tutu;
...
} quux_t;

void init_blah(quux_t* q, bar_t k, int i, int j, etc)
{
q->tata = i;
q->tutu = j;
init_bouh(&(k->toto), i, j);
}

void init_bouh(bar_t* b, int i; int j)
{
int x, y, z;
*b = malloc(i * sizeof(foo_t*));
for(x=0; x<i; ++x)
{
(*b)[x] = malloc(j * sizeof(foo_t));
for(y=0; y<j; y++)
{
(*b)[x][y].un = malloc(LENGTH1);
(*b)[x][y].deux = malloc(LENGTH1);
(*b)[x][y].trois = malloc(LENGTH1);
}
}
}


/* tout un tas de declarations ... */
quux_t* q;
bar_t b;
init_blah(q, b, x, y);
ret = q->toto[i][j].un[k]; /* ici, le segfault */
/* sachant que les valeurs i j et k sont dans le bon intervalle */
/* k <LENGTH1, j < au j de l'init, et i < au i de l'init */
...

Avatar
Éric Lévénez
Le 8/04/04 16:23, dans <c53n96$29ks$, « Tutu »
a écrit :

j'ai un leger soucis pour initialiser correctement une structure.

Voici le code:

typedef struct foo_s {
/* ces trois champs sont de meme longueur LENGHT1 */


Là ces 3 champs sont des pointeurs, donc ils ont la longueur de
sizeof(char *), ce que pointent ces pointeurs peut varier. Tout comme ces
pointeurs peuvent ne pas être initialisées ou valoir NULL.

char* un;
char* deux;
char* trois;
} foo_t;

typedef foo_t** bar_t;


Mauvaise idée de masquer un pointeur dans un typedef. Là avec une notion de
pointeur de pointeur, cela aggrave les risques d'erreur d'utilisation.

typdef struct quux_s {
bar_t toto;


toto est un pointeur, pas les autres. Cela est masqué.

int tata;
int tutu;
...
} quux_t;

Je souhaite en fait initialiser une variable de type quux_t,
sachant que "un" "deux" et "trois" sont de longueur N, et que
toto est un tableau a deux dimensions, K et L (les valeurs ne sont
pas connues a la compilation, d'ou les pointeurs...).

j'ai pense a quelque chose dans ce gout-la :

void init_blah(quux_t* q, bar_t k, int i, int j, etc)
{
q->tata = i;
q->tutu = j;
init_bouh(&(k->toto), i, j);
}

et

void init_bouh(bar_t* b, int i; int j)


b est l'adresse d'un tableau de pointeurs.

{
int x, y, z;
*b = malloc(i * sizeof(foo_t*));


Le fait d'avoir masqué le pointeur par un type intermédiaire oblige à
utiliser foo_t pour avoir la taille et bar_t pour savoir où le mettre. Pas
joli d'utiliser ainsi 2 types.

for(x=0; x<i; ++x)
{
*b[x] = malloc(j * sizeof(foo_t));


Comme le type de b n'est pas un simple pointeur mais un pointeur de
pointeurs, il y a mélange et là aussi obligation d'utiliser 2 types foo_t et
bar_t. Mais en fait le plus grave est que la valeur du malloc aille là où
pointe b[x], alors que tu voulais que cette valeur aille dans le tableau de
pointeurs.

(*b)[x] = malloc(j * sizeof(foo_t));

for(y=0; y<j; y++)
{
*b[x][y].un = malloc(LENGTH1);
*b[x][y].deux = malloc(LENGTH1);
*b[x][y].trois = malloc(LENGTH1);


Identique qu'au dessus. Le mascage de la vraie nature de b fait que
l'écriture de ce type d'expression n'est pas clair, d'où le problème.

(*b)[x][y].xxx = yyy;

}
}
}

J'ai volontairement omis les verifications de retour de malloc().
Sur ce code, j'ai un segfault des l'allocation d'espace pour "un",
une idee ?


Ne pas masquer la nature d'un pointeur par un typedef. Tu n'es pas le
premier à qui cela a entraîné des erreurs, et hélas tu ne seras pas le
dernier... Après coup, certains argumentent que cela n'est pas la cause
directe de leurs erreurs, ce qui est vrai, mais en tout cas cela y a
contribué.

--
Éric Lévénez -- <http://www.levenez.com/>
Unix is not only an OS, it's a way of life.

Avatar
Tutu
Le 8/04/04 16:23, dans <c53n96$29ks$, « Tutu »
a écrit :

j'ai un leger soucis pour initialiser correctement une structure.

Voici le code:

typedef struct foo_s {
/* ces trois champs sont de meme longueur LENGHT1 */


Là ces 3 champs sont des pointeurs, donc ils ont la longueur de
sizeof(char *), ce que pointent ces pointeurs peut varier. Tout comme ces
pointeurs peuvent ne pas être initialisées ou valoir NULL.


En fait quand je disais 'longueur', je parlais de la place que j'allais
alloue via malloc(LENGHT1) ... je reconnais que c'etait pas clair.


char* un;
char* deux;
char* trois;
} foo_t;

typedef foo_t** bar_t;


Mauvaise idée de masquer un pointeur dans un typedef. Là avec une notion de
pointeur de pointeur, cela aggrave les risques d'erreur d'utilisation.


c'est sur, mais sur le coup je preferais ne pas me trimballer des declarations
a base de f(foo_t***, ...); meme si je sais que masquer un pointeur peut etre
une source de pepins, c'est bon de me le marteler, merci.

P.


Avatar
Richard Delorme

/* tout un tas de declarations ... */
quux_t* q;
bar_t b;
init_blah(q, b, x, y);


q n'est pas initialisé ici. C'est un oubli de recopiage ou la source de
l'erreur ?

ret = q->toto[i][j].un[k]; /* ici, le segfault */
/* sachant que les valeurs i j et k sont dans le bon intervalle */
/* k <LENGTH1, j < au j de l'init, et i < au i de l'init */
...


--
Richard

Avatar
Tutu
Bon, etant donne que je me plante a chaque recopiage, je vais faire un c/c
des fonctions/types/structures incriminees.


------------------------ toto.h -----------------------
/* garde sur TOTO_H + inclusions des .h qui vont bien*/

typedef struct ligne_s {

char* ligne;
char* policy;
char* statut;

} ligne_t;


typedef struct memoire_s {

ligne_t** ensemble;
unsigned char associativite;
unsigned char nb_ensembles;
unsigned short longueur_ligne;

} memoire_t;


void init_ensembles(ligne_t*** s,
unsigned int a,
unsigned int n);

void init_memoire(memoire_t* memptr,
ligne_t** ensembles,
unsigned int associativite,
unsigned int nb_ensembles,
unsigned short longueur_ligne);

data_t acces_memoire(memoire_t* memptr,
unsigned int addresse,
short longueur,
int data);

--------------------------- fin toto.h --------------------

--------------------------- toto.c ------------------------
/* inclusion des .h qui vont bien */

void
init_ensembles(ligne_t*** s,
unsigned int as,
unsigned int nensembles)
{
int i, j;
*s = malloc(as * sizeof(ligne_t*));
for(i=0; i<as; ++i)
{
(*s)[i]=malloc(nensembles * sizeof(ligne_t));
for(j=0; j<nensembles; ++j)
{
(*s)[i][j].policy=malloc(sizeof(char*));
(*s)[i][j].ligne=malloc(sizeof(char*));
(*s)[i][j].statut=malloc(sizeof(char*));
memset((*s)[i][j].policy, 0, (size_t)LONGUEUR_LIGNE);
memset((*s)[i][j].ligne, 0, (size_t)LONGUEUR_LIGNE);
memset((*s)[i][j].statut, MEMOIRE_CLEAN, (size_t)LONGUEUR_LIGNE);
/* LONGUEUR_LIGNE est un #define, et vaut une puissance de 2... */
/* MEMOIRE_CLEAN : idem, mais juste un booleen */
}
}
}


void
init_memoire(memoire_t* memoire,
ligne_t** ensembles,
unsigned int as,
unsigned int nensembles,
unsigned short longueur_ligne)
{
memoire=malloc(sizeof(memoire_t));
memoire->associativite = as;
memoire->nensembles = nensembles;
memoire->longueur_ligne = longueur_ligne;
init_ensembles(&(memoire->ensembles), as, nensembles);
(void)fprintf(stderr, "as=%d; nensembles=%d, linesize=%dn",
memoire->associativite,
memoire->nensembles,
memoire->longueur_ligne);
}

data_t
acces_memoire (memoire_t* memoire,
char type_acces,
addresse_t addresse,
short taille,
data_t donnee)
{
unsigned int offset = 0;
unsigned int index = 0;
int i = 0;
unsigned int found = 0;
data_t ret = 0x00000000;

offset = (unsigned int) (addresse & OFFSET_MASK);
index = (unsigned int) ((addresse & INDEX_MASK) >> OFFSET_LEN);
/* OFFSET_MASK, INDEX_MASK et OFFSET_LEN sont definis ailleurs ... */

for(i=0; i<ASSOCIATIVITE-1; ++i)
{
/***************************************************/
/* SEGFAULT ICI */
/***************************************************/
found = MAX(memoire->ensembles[i][index].lru[offset],
memoire->ensembles[i+1][index].lru[offset]);

}

return EXIT_SUCCESS;
}


----------------------- fin toto.c ---------------------------------

----------------------- main.c -------------------------------------
/* inclusion des .h qui vont bien */

int main(void)
{
...
memoire_t* memoire = NULL;
ligne_t** lignes = NULL;
unsigned int longueur_ligne = LONGUEUR_LIGNE;
unsigned int assoc = ASSOCIATIVITE;
unsigned int nb_lignes = NB_LIGNES;
init_memoire(memoire, lignes, assoc, nb_lignes, longueur_ligne);
acces_memoire(memoire, ECRITURE, 0x00000081, 4, 0x00000001);
...
}

----------------------- fin main.c ----------------------------------

Voila, c'est tout pour cette fois (et merci a ceux qui se sont interesses
a cet article).

P.
Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Tutu wrote:

typedef struct foo_s {
/* ces trois champs sont de meme longueur LENGHT1 */


Comment ça? Tu ne serais pas en train de confondre tableau et pointeur, non?

char* un;
char* deux;
char* trois;


par ce que là, je vois 3 pointeurs...

} foo_t;

typedef foo_t** bar_t;


Que je n'aime pas ça. Les pointeurs c'est pas sale. On peut les montrer.

En principe, on évite le suffixe '_t', car il est réservé à POSIX (et à
quelques types définis par la norme). J'utilise le suffixe '_s' quand c'est
un typedef. Sinon, le mot clé 'struct' est suffisament obligatoire et
explicite pour se suffire à lui-même.

Illustration:

typdef struct quux_s {


typedef struct quux {

bar_t toto;
int tata;
int tutu;
...
} quux_t;


} quux_s;

Je souhaite en fait initialiser une variable de type quux_t,
sachant que "un" "deux" et "trois" sont de longueur N, et que
toto est un tableau a deux dimensions, K et L (les valeurs ne sont
pas connues a la compilation, d'ou les pointeurs...).

j'ai pense a quelque chose dans ce gout-la :

void init_blah(quux_t* q, bar_t k, int i, int j, etc)
{
q->tata = i;
q->tutu = j;
init_bouh(&(k->toto), i, j);
}

et

void init_bouh(bar_t* b, int i; int j)
{
int x, y, z;
*b = malloc(i * sizeof(foo_t*));
for(x=0; x<i; ++x)
{
*b[x] = malloc(j * sizeof(foo_t));
for(y=0; y<j; y++)
{
*b[x][y].un = malloc(LENGTH1);
*b[x][y].deux = malloc(LENGTH1);
*b[x][y].trois = malloc(LENGTH1);
}
}
}

J'ai volontairement omis les verifications de retour de malloc().
Sur ce code, j'ai un segfault des l'allocation d'espace pour "un",
une idee ?


Oui:

"Plus c'est simple, moins c'est compliqué"
-- Proverbe Gibi.

Poste le code exact qui compile mais qui provoque le bug. Réduit le au
minimum qui provoque le bug.

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Tutu wrote:

Bon, etant donne que je me plante a chaque recopiage, je vais faire un c/c
des fonctions/types/structures incriminees.


Ah, enfin!

<copié/collé, découpage, projet, compilation...>

Je craque! C'est si compliqué que ça de poster un code qui compile?

Compiling TOTO.C:
Error TOTO.H 42: Declaration syntax error

Y'a un bug à la ligne 42 ! ARF!!! (data_t n'est pas défini). On est censé
faire une heure de retro-engineering pour avancer ?

Warning TOTO.C 10: Call to function 'malloc' with no prototype
Warning TOTO.C 10: Nonportable pointer conversion
Warning TOTO.C 13: Call to function 'malloc' with no prototype
Warning TOTO.C 13: Nonportable pointer conversion
Warning TOTO.C 16: Call to function 'malloc' with no prototype
Warning TOTO.C 16: Nonportable pointer conversion
Warning TOTO.C 17: Call to function 'malloc' with no prototype
Warning TOTO.C 17: Nonportable pointer conversion
Warning TOTO.C 18: Call to function 'malloc' with no prototype
Warning TOTO.C 18: Nonportable pointer conversion
Error TOTO.C 19: Undefined symbol 'size_t'
Error TOTO.C 19: Function call missing )
Error TOTO.C 20: Function call missing )
Error TOTO.C 21: Undefined symbol 'MEMOIRE_CLEAN'
Error TOTO.C 21: Function call missing )
Warning TOTO.C 34: Call to function 'malloc' with no prototype
Warning TOTO.C 34: Nonportable pointer conversion
Error TOTO.C 36: Undefined symbol 'nensembles'
Error TOTO.C 38: Undefined symbol 'ensembles'
Error TOTO.C 39: Undefined symbol 'stderr'
Error TOTO.C 41: Undefined symbol 'nensembles'
Warning TOTO.C 42: Call to function 'fprintf' with no prototype
Warning TOTO.C 43: Parameter 'ensembles' is never used
Error TOTO.C 45: Declaration syntax error


Compiling MAIN.C:
Error TOTO.H 42: Declaration syntax error
Error MAIN.C 6: Undefined symbol 'NULL'
Error MAIN.C 8: Undefined symbol 'LONGUEUR_LIGNE'
Error MAIN.C 9: Undefined symbol 'ASSOCIATIVITE'
Error MAIN.C 10: Undefined symbol 'NB_LIGNES'
Error MAIN.C 12: Undefined symbol 'ECRITURE'
Warning MAIN.C 12: Call to function 'acces_memoire' with no prototype
Warning MAIN.C 13: Function should return a value


--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Tutu
In 'fr.comp.lang.c', Tutu wrote:

Bon, etant donne que je me plante a chaque recopiage, je vais faire un c/c
des fonctions/types/structures incriminees.


Ah, enfin!

<copié/collé, découpage, projet, compilation...>

Je craque! C'est si compliqué que ça de poster un code qui compile?


Ben... oui. Le code (que je reprends, ce n'est pas le mien a l'origine) est pas
du tout modulaire, et c'est ce que je suis en train de faire (le debuguer et le
rendre modulaire), mais y'a des dizaines de milliers de lignes de code dans 3
fichiers sources seulement.
J'ai fait ce que j'ai pu, et je sais bien que c'etait pas compilable tel quel,
desole, mais j'ai circoncis au mieux la zone qui pose probleme ...
Le truc c'est que je me suis dit que le bug devait etre grossier, et que comme
j'ai le pif dedans depuis quelques temps, je suis incapable de le voir, aussi,
j'avais espere que l'un d'entre vous le debusque aisement (je ne suis pas du
tout programmeur de formation, ni de metier, d'ailleurs).

P.


Avatar
Tutu
In 'fr.comp.lang.c', Tutu wrote:

Bon, etant donne que je me plante a chaque recopiage, je vais faire un c/c
des fonctions/types/structures incriminees.


Ah, enfin!

<copié/collé, découpage, projet, compilation...>

Je craque! C'est si compliqué que ça de poster un code qui compile?


Ben... oui. Le code (que je reprends, ce n'est pas le mien a l'origine) est pas
du tout modulaire, et c'est ce que je suis en train de faire (le debuguer et le
rendre modulaire), mais y'a des dizaines de milliers de lignes de code dans 3
fichiers sources seulement.
J'ai fait ce que j'ai pu, et je sais bien que c'etait pas compilable tel quel,
desole, mais j'ai circoncis au mieux la zone qui pose probleme ...
^^^

hum, je suis fatigue :)
Le truc c'est que je me suis dit que le bug devait etre grossier, et que comme
j'ai le pif dedans depuis quelques temps, je suis incapable de le voir, aussi,
j'avais espere que l'un d'entre vous le debusque aisement (je ne suis pas du
tout programmeur de formation, ni de metier, d'ailleurs).

P.




1 2