Open renvoie 0

Résolu
MARQUISvincent Messages postés 1 Date d'inscription mardi 26 mai 2009 Statut Membre Dernière intervention 14 juin 2009 - 14 juin 2009 à 14:43
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 - 15 juin 2009 à 10:21
Bonjour
J'essaye d'ecrire dans un fichier avec le code suivant

  if (filedesc=open("audit.txt",O_CREAT | O_WRONLY |O_APPEND ,0666)==-1){
                perror("open");
                exit(1);
            }
  printf("filedesc:%d\n",filedesc);

  if (write(filedesc,buf,strlen(buf))==-1){
                perror("write");
                exit(1);
            }

Le fichier est bien crée s'il n'existe pas, par contre filedesc est égale a 0 et buf s'affiche dans mon terminal.
Je ne comprend pas pourquoi je n'obtient pas un descriteur de fichier correcte qui me permette d'ecrire dans mon fichier

14 réponses

uaip Messages postés 1466 Date d'inscription mardi 20 février 2007 Statut Membre Dernière intervention 7 février 2011
14 juin 2009 à 19:04
Salut,
Pour moi, c'est logique. Il y a des priorités dans les opérateurs. Et l'opérateur = = est prioritaire sur l'affectation (=).
lectpe se trompe en disant que ta syntaxe est incorrecte en C. C'est tout fait autorisé, mais pas logique dans ce cas.

Exemple :
int a =0 == 1;
C'est d'abord la partie droite de l'affectation (en bleu) qui est analysée, et '0 == 1' est faux, donc cette expression vaut 0, d'où 0 est affecté à 'a'.

C'est pareil pour toi : (filedesc=open("audit.txt",O_CREAT | O_WRONLY |O_APPEND ,0666)==-1)
open() se déroule correctement et retourne sans doute le descripteur de ton fichier (descripteur > 0).
Or, en testant la partie bleue, ton descripteur n'est pas égal à -1 (puisque tu dis que la création du fichier se fait correctement). Donc l'espression en bleu vaut 0, d'où 0 est affecté à filedesc.

Il suffit de rajouter des parenthèses autour de ton affectation pour chambouler les priorités des opérateurs, comme suit :
( ( filedesc =open("audit.txt",O_CREAT | O_WRONLY |O_APPEND ,0666))==-1)
Là, filedesc est affecté par la valeur de retour de open() et ensuite seulement est comparée à -1.

Cordialement, uaip.
3
lectpe Messages postés 162 Date d'inscription lundi 12 novembre 2007 Statut Membre Dernière intervention 17 juillet 2010 3
14 juin 2009 à 18:28
Bonjour.

Déjà, ça c'est incorrect en C :

(filedesc=open("audit.txt",O_CREAT | O_WRONLY |O_APPEND ,0666)==-1)
Tu ne peux pas mettre un et un dans la même parenthèse.

Cordialement, Grégory.
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
14 juin 2009 à 19:07
Salut,
lectpe a mis le doigt sur le problème. Quoique rien ne t'empêche vraiment de mettre un et un dans une même parenthèse.

L'opérateur == est prioritaire sur l'opérateur =.
Donc le compilateur fait :
filedesc = (open("audit.txt",O_CREAT | O_WRONLY |O_APPEND ,0666)==-1)

Autrement dit il affecte le résultat d'un test booléen à fileDesc, en l'occurence 0 (False), car ton fichier s'est ouvert correctement (Mais le descripteur de fichier est parti dans la nature).

Conclusion : ne jamais faire d'affectation et de tests en même temps, même si le C le permet.
Cela nuit à la lisibilité et est générateur d'erreurs.
0
cs_rt15 Messages postés 3874 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 7 novembre 2014 13
14 juin 2009 à 19:08
Message redondant avec uaip, désolé...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
14 juin 2009 à 19:20
Salut,

Un petit post juste pour dire que si tout le monde compilais avec de bons flags il y aurait tout de suite moins de problèmes. Ici, -Wparentheses (ou mieux, -Wall) aurais émis un warning prévenant de la potentielle erreur.
0
lectpe Messages postés 162 Date d'inscription lundi 12 novembre 2007 Statut Membre Dernière intervention 17 juillet 2010 3
14 juin 2009 à 19:25
Oui vous avez raison, c'est permis en C, mais comme je ne l'utilise jamais, je ne savais pas que c'était autorisé. Désolé.
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
14 juin 2009 à 20:34
Puisqu'on parle de flag, voici les flags que j'utilise usuellement:

C ansi:
Release: gcc -W -Wall -Wextra -ansi -pedantic -Werror -DNDEBUG -pedantic-errors -03 *.c
Debug: gcc -W -Wall -Wextra -ansi -pedantic -g3 -lduma *.c

C 99
Release: gcc -W -Wall -Wextra -std=c99 -pedantic -pedantic-errors -DNDEBUG -03 *.c
Debug: gcc -W -Wall -Wextra -std=c99 -g3 -lduma *.c

C++
Release: g++ -W -Wall -Wextra -Wabi -pedantic -pedantic-errors -DNDEBUG -03 *.cc
Debug: g++ -W -Wall -Wextra -Wabi -pedantic -g3 -lduma -D_GLIBCXX_DEBUG *.cc

Note: duma est un fork de eletric fence (-lefence), qui est, lui, tenu à jour.
Si vous avez des remarques, ou d'autre flags intéressant, je suis preneur.
0
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
14 juin 2009 à 21:14
«duma est un fork de eletric fence (-lefence), qui est, lui, tenu à jour.»
Pour avoir utilisé efence, je peux dire que je préfère grandement l'usage de valgrind que de ce genre de libs.

«Si vous avez des remarques, ou d'autre flags intéressant, je suis preneur.»
-W est l'ancien nom de -Wextra, il est donc complètement inutile de mettre les deux à la fois vu que c'est le même ;)

Les flags que j'utilise habituellement pour du C ansi avec une vielle version de gcc (et donc quelques flags de moins) :
-W -Wall -Werror -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Winline -ansi -pedantic
A rajouter : -ggdb3 pour le debug et -O3 pour le realease.
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
14 juin 2009 à 21:20
Perso j'utilise les deux. Duma me permet de vérifier que je ne déborde pas ou que je ne tape pas n'importe où dans la mémoire. J'utilise valgrind moins souvent, pour détecter les fuites mémoires plus qu'autre chose.

Ok, merci pour le -W <=> -Wextra. Je n'étais pas à jour. Je prends note des autres flags (je ferais une recherche sur leur signification, bien que le nom soit explicite pour la grande majorité).

Néanmoins, j'ai encore une question: qu'apporte -ggdb3 de plus que -g ?
0
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
14 juin 2009 à 23:20
«Duma me permet de vérifier que je ne déborde pas ou que je ne tape pas n'importe où dans la mémoire.»
Valgrind aussi, et bien mieux que ces libs. Duma et efence ne font que "surcharger" malloc et autres fonctions de ce genre afin "d'encadrer" chaque allocation mémoire par une portion de mémoire ne t'appartenant pas. Ceci a pour conséquence de ne reporter que les débordement en mémoire effectués sur ce qui a été aloué via ces appels systèmes. Un exemple de débordement que duma et efence ne peuvent pas voir :

#include <stdlib.h>
#include <stdio.h>

int     main(void)
{
  int   tab[2];
  int   x;
  char *str;

  for (x = 0; x <= 2; x++)
    printf("Val: %d\n", tab[x]);
  str = malloc(42);
  if (str != NULL)
    free(str);
  return 0;
}

tycho@uraniborg-> cc test.c -L. -lduma -lpthread
tycho@uraniborg-> ./a.out
DUMA 2.5.15 (static library)
Copyright (C) 2006 Michael Eddington <meddington@gmail.com>
Copyright (C) 2002-2008 Hayati Ayguen <h_ayguen@web.de>, Procitec GmbH
Copyright (C) 1987-1999 Bruce Perens

Val: 134537656
Val: -1078404664
Val: 2
tycho@uraniborg-> valgrind ./a.out > /dev/null 2> out.txt ; tail -5 out.txt
12979== ERROR SUMMARY: 44 errors from 5 contexts (suppressed: 15 from 1)
12979== malloc/free: in use at exit: 0 bytes in 0 blocks.
12979== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
12979== For counts of detected errors, rerun with: -v
12979== All heap blocks were freed -- no leaks are possible.
tycho@uraniborg->

Et oui, j'ai fait un débordement en mémoire que duma n'a pas détecté. On remarquera l'usage du malloc qui est là uniquement pour que le petit copyright de duma s'affiche ainsi que le fait que valgrind n'indique pas le nombre d'alloc/free effectués (a cause de la surcharge faite par duma).
Contrairement a celà, valgrind m'indique bien le dit débordement. Si je compile avec les symboles de debug il me dit même la ligne a laquelle l'erreur s'est produite.

Conclusion: valgrind rules

«qu'apporte -ggdb3 de plus que -g ?»
Il me semble que ça a un rapport avec les extensions de gdb mais je ne suis pas certain. En fait si j'utilsie -ggdb3 et non simplement -g c'est surtout parce que j'ai un prof qui préfère ça, je lui demanderai a l'occasion (tu as éveillé ma curiosité là).
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
14 juin 2009 à 23:33
Je sais comment fonctionne lefence/lduma. Certe ça ne détecte pas les allocations statiques, mais fait très bien le reste. La raison pour laquelle j'utilise duma, est que je n'ai pas besoin de lancer en continue un valgrind, je code comme si de rien n'était. Très pratique d'ailleurs pour un make check (à coup de valgrind ça serait vachement plus galère). Néanmoins, comme je l'ai précisé, je passe toujours un coup de valgrind (en virant évidemment -lefence/-lduma) parce que comme je l'ai évoqué, duma ne détecte pas tout (ne serait-ce que le nombre de free vs malloc, tout simplement).

En passant, si je peux me permettre, il me semble que (à vérifier):
  if (str != NULL)
    free(str);
est redondant. Un simple free(str) suffit puisque free, tout comme new en C++, vérifie la nullité de ce qui est passé en argument.
free(NULL); est valide, et ne fait rien.

Je suis fortement intéressé par la réponse -g vs -ggdb3.
0
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
15 juin 2009 à 00:28
Je t'accorde que valgrind n'est pas toujours tip top a utiliser et que duma a quelques bons avantages. Enfin, après a chacun ses goûts ^^

Pour ce qui est du free(NULL), oui le pointeur est testé, mais j'ai pris l'habitude a cause des implémentations foireuses de certaines fonctions (dans ma jeunesse j'ai été traumatisé par un strdup(NULL) qui segfault :p).
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
15 juin 2009 à 00:44
Et pourtant ce n'est pas un bug !

From the ISO/IEC 9899:1999 (E), 7.1.4, clause 1

Each of the following statements applies unless explicitly stated

otherwise in the detailed descriptions that follow: If an argument to

a function has an invalid value (such as a value outside the domain of

the function, or a pointer outside the address space of the program,

or a null pointer, or a pointer to non-modifiable storage when the

corresponding parameter is not const-qualified) or a type (after

promotion) not expected by a function with variable number of arguments,

the behavior is undefined.

En gros, strdup(NULL) a un comportement indéfini, puisque ce qui lui est passé en argument n'est pas considéré comme quelque chose de cohérent/valide.

Alors pourquoi free(NULL) est lui, valide ?
Je pense tout simplement que la logique suivante a été appliquée:
- Libérer quelque chose de déjà libéré n'est pas nécessaire => free(NULL) ne fait rien.
- Dupliquer quelque chose de non existant ne devrait pas arriver => indéfinis.
0
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
15 juin 2009 à 10:21
Pour ma part, comme comportement non défini j'entends plus «retour de la fonction indéfini», laissant alors le choix, dans le cas d'un pointeur null, de le définir comme une situation anormale ou pas. Un gros segfault sur NULL ça reste de mon point de vue une erreur assez grave. Ceci dit, ce que tu cites me comforte dans ma politique de précaution vis-a-vis des différentes implémentations de la libc.

«- Dupliquer quelque chose de non existant ne devrait pas arriver => indéfinis.»
Vouloir ne rien dupliquer revient a ne rien faire, donc retourner NULL sans segfaulter serait le plus logique.
0
Rejoignez-nous