OVH Cloud OVH Cloud

Ecrire une structure dans un fichier binaire

31 réponses
Avatar
citrouille
En fait, j'ai une structure très simple que je veux écrire dans un
fichier :

typedef struct{
char *txt;
int x;
}TEST;


Ecriture dans le fichier :

TEST *t = (TEST *)malloc(sizeof(TEST));
FILE *file;

t->txt = "pouet pouet";
t->x = 257;

file = fopen("fichier_test", "rb");
write(file, t, sizeof(TEST));
fclose(file);

Quand je regarde le fichier créé avec un éditeur héxadécimal, je
constate que ma chaine de caractere n'est pas enregistré, mais
seulement son adresse (je pense), car j'ai beau changer la chaine,
c'est toujour la meme chose d'enregistré. tandi que le int lui est
bien enregistré dans le fichier.

Pourrais-je avoir la bonne technique pour faire bien cette écriture ?

10 réponses

1 2 3 4
Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', "Stephane Legras-Decussy"
wrote:

Avec ton raisonnement on ne pourrait pas faire :
char *chaine = "pouet pouet";


char *chaine=" pouet pouet" ; OK

mais

char * chaine ;
chaine = "pouet pouet"; NON


Si !

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/


Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Christophe Le Gal wrote:

C'est, il me semble, egalement le cas pour "toto"[0]='X' ;


Le résultat de ce code est indéfini. En embarqué, les chaines sont souvent
codées 'en dur' dans la PROM. Ecrire dans une PROM est un délit passible de
la cour martiale.

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Christophe Le Gal wrote:

Juste pour etre bien sur de comprendre :

Un programme qui ferait :
scanf("%d", &index) ;


Correct, si 'index' est de type 'int'.

printf("%d", tab[index]) ;


Correct, si tab[...] est de type 'int', que 'index' est dans les limites
permises par la définition (ou l'initialisation) de 'tab' et que 'tab[index]'
est correctement initialisé.

serait interdit par la norme ?


Non, Pourquoi ?

On ne peut pas garantir que index sera dedans ou dehors les limites
de tab. On doit meme pouvoir en choisissant bien "index" taper
pile dans l'adresse d'une chaine constante.
Donc si je comprends bien c'est un UB.


Personne n'a dit qu'un UB était interdit par la norme. Il n'est pas interdit
d'écrire un UB, (sinon, ce ne serait pas un UB), mais il faut simplement être
conscient que la norme de définit pas tout, et que certaines syntaxes, bien
que légales, invoquent un UB. Se fier à la seule validité syntaxique ne
suffit pas à garantir que le code soit correct.

Qu'est-ce qui ferait que ce programme serait du C legal, et mes
exemples non ?


Encore une fois, un UB ne rend pas le code illegal, mais simplement
dangereux. On a le droit d'utiliser gets(), mais un professionel sérieux ne
le fera pas.

Le fait que dans mes exemples on peut _statiquement_ prouver
qu'on va au devant de graves problemes ?
Mais dans ce cas ca voudrait dire que l'intelligence du compilo
a une influence sur la norme. Ou la norme fixe-t-elle un
niveau de facilite de detection, interdisant les erreurs "facilement
detectables" ?


La norme ne définit pas les compilateurs ni les analyseurs de codes. La norme
autorise certains comportements, en interdit d'autre. Pour faire simple, tout
ce qui n'est pas défini relève de l'UB. C'est un bug (même si il est latent).

*((char *)(0)) = '' ; est interdit ?


Déréférencer le pointeur NULL invoque un comportement indéfini.

x = 0 ;
*((char *)(0+x)) = '' ?


Déréférencer un pointeur qui n'a pas été initialisé par

- l'adresse d'un tableau
- l'adresse retournée par malloc()
- la valeur d'un pointeur valide

invoque un comportement indéfini.

Tes deux exemples sont causent egalement des UB. Le premier parce que tu
"crees" un pointeur vers une zone de memoire qui /a priori/ ne
t'appartient pas.


C'est interdit ?
Il me semblant que c'est plutot en le dereferencant que je faisait
une erreur _runtime_


Certes, mais quel intéret d'écrire du code qu'on a pas l'intention
d'exécuter?

char t[100] ;
char *p ;
char *end ;

p=&(t[0]) ;


Une façon compliquée d'écrire

p = t + 0

ou encore plus simplement:

p = t;

end = p+100 ;
for(;p<end;p++) est alors interdit aussi je suppose.


Non, c'est défini par la norme, justement pour traiter ce cas là, qui est
idiomatique.

Je connais des gens qui programment salement. Mais je n'ai encore jamais
vu qqn qui s'amuse a modifier des chaines constantes "pour de vrai".
Surtout que ce serait bien con, vu que, norme ou pas, ub ou pas,
ca peut faire un segfault, et la facon de creer les chaines constantes
depend du compilateur (ce qui etait d'ailleurs le point que j'illustrait
ici).


C'est précisément par ce que ça /peut/provoquer un segfault, que l'on parle
de UB. Il y a des systèmes qui accèptent ça sans rien dire, c'est pour ça
qu'un UB est si dangereux.

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/


Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', "Stephane Legras-Decussy"
wrote:

chaine = " pouet pouet"; // correct.
chaine = "truc bidule machin chose"; //encore correct.


ok...les bras m'en tombent....

je me trimbalais cette certitude depuis toujours...
la honte... :-(


C'est pas grave. Tu as mis au point tes connaissances. Cette journée aura
donc été fructueuse. Il fait penser positivement!

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/


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

TEST *t = (TEST *)malloc(sizeof(TEST));
FILE *file;

t->txt = "pouet pouet";
t->x = 257;

file = fopen("fichier_test", "rb");
write(file,t->txt, strlen(t->txt));

write(file,&t->x, sizeof(int));
fclose(file);



Mouais... Et on relis comment?

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/


Avatar
Christophe Le Gal
Personne n'a dit qu'un UB était interdit par la norme. Il n'est pas interdit
d'écrire un UB, (sinon, ce ne serait pas un UB), mais il faut simplement être
conscient que la norme de définit pas tout, et que certaines syntaxes, bien
que légales, invoquent un UB. Se fier à la seule validité syntaxique ne
suffit pas à garantir que le code soit correct.


Si personne ne l'a dit, il n'y a pas de discussion. Mais c'est bien parce
que ca a ete dit que ce thread dure si longtemps. Et que je cherche,
sincerement a savoir si c'est illegal ou non. Et ta reponse confirme
parfaitement ce qui etait ma pensee initiale, mais contedit ce dont
j'avais fini par etre convaincu par les interventions successives.

A savoir que tu dis que :

Encore une fois, un UB ne rend pas le code illegal, mais simplement
dangereux. On a le droit d'utiliser gets(), mais un professionel sérieux ne
le fera pas.


C'est precisement ce que j'ai cherche a defendre; bien que j'ai fini par
me laisser convaincre du contraire, et a me replier sur une position
plus en retrait ("meme si mon code est illegal, le fait qu'il compile
prouve normalement qu'il est syntaxiquement legal").
Et maintenant j'ai a nouveau un doute.

Bref, sans revenir sur le sujet initial (avec tous ces gens qui reviennent de
vacances ce vieux thread a ete rechauffe plusieurs fois), question :
- Un code contenant un UB est il illegal ou seulement dangeureux ?
Par illegal je n'entends pas "passible de la cour martiale" bien sur.
Autrement dit, est-ce qu'un code contenant un UB est du C dangeureux
ou n'est pas du C.
1[0] = 0, ca n'est pas du C. ok ?
"toto"[0] = '', est-il du C pourri, ou n'est-il pas du C ?

[quand meme autre remarque au passage : mon code avait-il l'air
professionnel ? Bien entendu qu'un professionnel ne fait pas ca. C'etait
sense etre clair].

C'est précisément par ce que ça /peut/provoquer un segfault, que l'on parle
de UB. Il y a des systèmes qui accèptent ça sans rien dire, c'est pour ça
qu'un UB est si dangereux.


On est bien d'accord. Et dans mon tout premier post je disais deja que
c'etait un UB (sans utiliser ces 2 lettres certes, mais quand je disais
que ca compile mais qu'apres ca n'est pas garanti de marcher, c'est
ce que j'expliquais, "avec mes mots a moi").

Cordialement
--
Christophe Le Gal

Avatar
Yves ROMAN

Bref, sans revenir sur le sujet initial (avec tous ces gens qui reviennent de
vacances ce vieux thread a ete rechauffe plusieurs fois), question :
- Un code contenant un UB est il illegal ou seulement dangeureux ?
Par illegal je n'entends pas "passible de la cour martiale" bien sur.
Autrement dit, est-ce qu'un code contenant un UB est du C dangeureux
ou n'est pas du C.
1[0] = 0, ca n'est pas du C. ok ?
"toto"[0] = '', est-il du C pourri, ou n'est-il pas du C ?

[quand meme autre remarque au passage : mon code avait-il l'air
professionnel ? Bien entendu qu'un professionnel ne fait pas ca. C'etait
sense etre clair].


Autre sujet a propos de l'apparence :
Il faudrait définir la notion de C pourri : les sources de l'IOCCC sont ils du C
pourri, même s'il ne contiennent pas d'UB et fonctionnent ?

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Christophe Le Gal wrote:

Bref, sans revenir sur le sujet initial (avec tous ces gens qui
reviennent de vacances ce vieux thread a ete rechauffe plusieurs fois),
question : - Un code contenant un UB est il illegal ou seulement
dangeureux ?


Dangereux. Il ne peut pas êre illégal, puisqu'il est non défini.

Par illegal je n'entends pas "passible de la cour martiale"
bien sur. Autrement dit, est-ce qu'un code contenant un UB est du C
dangeureux ou n'est pas du C.


Dangereux.

1[0] = 0, ca n'est pas du C. ok ?


Ok.

"toto"[0] = '', est-il du C pourri, ou n'est-il pas du C ?


Du C dangereux.

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
AG
Autrement dit, est-ce qu'un code contenant un UB est du C dangeureux
ou n'est pas du C.
1[0] = 0, ca n'est pas du C. ok ?
"toto"[0] = '', est-il du C pourri, ou n'est-il pas du C ?


Est ce qu'une 4L est une voiture pourrie, ou ce n'est pas une voiture ?
-> on s'en fout, on sait bien ce qu'est une 4L. Fin de la discussion.

Avatar
Bertrand Mollinier Toublet
Christophe Le Gal wrote:
Personne n'a dit qu'un UB était interdit par la norme. Il n'est pas interdit
d'écrire un UB, (sinon, ce ne serait pas un UB), mais il faut simplement être
conscient que la norme de définit pas tout, et que certaines syntaxes, bien
que légales, invoquent un UB. Se fier à la seule validité syntaxique ne
suffit pas à garantir que le code soit correct.



Si personne ne l'a dit, il n'y a pas de discussion. Mais c'est bien parce
que ca a ete dit que ce thread dure si longtemps. Et que je cherche,
sincerement a savoir si c'est illegal ou non. Et ta reponse confirme
parfaitement ce qui etait ma pensee initiale, mais contedit ce dont
j'avais fini par etre convaincu par les interventions successives.

A savoir que tu dis que :


Encore une fois, un UB ne rend pas le code illegal, mais simplement
dangereux. On a le droit d'utiliser gets(), mais un professionel sérieux ne
le fera pas.



C'est precisement ce que j'ai cherche a defendre; bien que j'ai fini par
me laisser convaincre du contraire, et a me replier sur une position
plus en retrait ("meme si mon code est illegal, le fait qu'il compile
prouve normalement qu'il est syntaxiquement legal").
Et maintenant j'ai a nouveau un doute.

Bref, sans revenir sur le sujet initial (avec tous ces gens qui reviennent de
vacances ce vieux thread a ete rechauffe plusieurs fois), question :
- Un code contenant un UB est il illegal ou seulement dangeureux ?


C'est une question de contexte. Dans le contexte de la norme du C, c'est
illegal. Dans un contexte de programmation reelle, il va certainment y
avoir un endroit dans ton code ou, du point de vue de la norme, un UB
est invoque (par exemple, un acces direct a la memoire: *((int
*)0xcafebabe) = 0x5). Heureusement, dans ces cas la, "quelqu'un" d'autre
(ton compilateur, ton OS, etc.) va te garantir la validite du code.

Par illegal je n'entends pas "passible de la cour martiale" bien sur.
Autrement dit, est-ce qu'un code contenant un UB est du C dangeureux
ou n'est pas du C.


Ce n'est pas du C, a entendre dans le sens de "ce n'est pas du C defini
par la norme du C". Maintenant, le degre de -pardonnez moi- dangerosite
depend des garanties externes a la norme que tu peux avoir. Pour etre
honnete, un code invoquant un UB est surtout pas portable, dans la
mesure ou quiconque te garantit la "validite" de l'UB ne sera
certainement pas la sur la plateforme a cote.

1[0] = 0, ca n'est pas du C. ok ?


Ah bin non, c'est syntaxiquement pas correct.

"toto"[0] = '', est-il du C pourri, ou n'est-il pas du C ?


Bah, pourri, pas pourri, c'est tres subjectif. C'est tout a fait correct
syntactiquement et semantiquement. Le style n'est pas forcement tres
approuve...

[quand meme autre remarque au passage : mon code avait-il l'air
professionnel ? Bien entendu qu'un professionnel ne fait pas ca. C'etait
sense etre clair].

Hehehe, a moins que tu ne veuilles eclaircir la commutativite de

l'operateur [], un code didactique ne fait pas ca non plus. <g>

C'est précisément par ce que ça /peut/provoquer un segfault, que l'on parle
de UB. Il y a des systèmes qui accèptent ça sans rien dire, c'est pour ça
qu'un UB est si dangereux.



On est bien d'accord. Et dans mon tout premier post je disais deja que
c'etait un UB (sans utiliser ces 2 lettres certes, mais quand je disais
que ca compile mais qu'apres ca n'est pas garanti de marcher, c'est
ce que j'expliquais, "avec mes mots a moi").

Oui. Cela dit, il est quand meme important, AMHA, de bien indiquer quand

un code donne invoque un UB, parce que, *dans le contexte de ce
newsgroup*, c'est une faute grave (en particulier a cause de l'atteinte
irremediable a la portabilite).

Je pense que ce que je reprochais le plus a ton post originale (la
fameuse contribution "dont on aurait pu se passer" :-), c'est que tu y
avais foutu pleins d'UB sans indiquer tres clairement combien c'est une
faute grave. Il vaut mieux commencer par se mefier des UB comme de la
peste, puis, au fur et a mesure que ton niveau progresse, apprendre dans
quelle mesure tu peux en faire un usage controle.

--
Bertrand Mollinier Toublet
"Uno no se muere cuando debe, sino cuando puede"
-- Cor. Aureliano Buendia


1 2 3 4