Open renvoie 0 [Résolu]

MARQUISvincent 1 Messages postés mardi 26 mai 2009Date d'inscription 14 juin 2009 Dernière intervention - 14 juin 2009 à 14:43 - Dernière réponse : TychoBrahe 1310 Messages postés samedi 31 janvier 2009Date d'inscription 5 juin 2013 Dernière intervention
- 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
Afficher la suite 

Votre réponse

14 réponses

Meilleure réponse
uaip 1473 Messages postés mardi 20 février 2007Date d'inscription 7 février 2011 Dernière intervention - 14 juin 2009 à 19:04
3
Merci
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.

Merci uaip 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 69 internautes ce mois-ci

Commenter la réponse de uaip
lectpe 163 Messages postés lundi 12 novembre 2007Date d'inscription 17 juillet 2010 Dernière intervention - 14 juin 2009 à 18:28
0
Merci
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.
Commenter la réponse de lectpe
cs_rt15 3982 Messages postés mardi 8 mars 2005Date d'inscription 7 novembre 2014 Dernière intervention - 14 juin 2009 à 19:07
0
Merci
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.
Commenter la réponse de cs_rt15
cs_rt15 3982 Messages postés mardi 8 mars 2005Date d'inscription 7 novembre 2014 Dernière intervention - 14 juin 2009 à 19:08
0
Merci
Message redondant avec uaip, désolé...
Commenter la réponse de cs_rt15
TychoBrahe 1310 Messages postés samedi 31 janvier 2009Date d'inscription 5 juin 2013 Dernière intervention - 14 juin 2009 à 19:20
0
Merci
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.
Commenter la réponse de TychoBrahe
lectpe 163 Messages postés lundi 12 novembre 2007Date d'inscription 17 juillet 2010 Dernière intervention - 14 juin 2009 à 19:25
0
Merci
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é.
Commenter la réponse de lectpe
cptpingu 3797 Messages postés dimanche 12 décembre 2004Date d'inscription 13 août 2018 Dernière intervention - 14 juin 2009 à 20:34
0
Merci
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.
Commenter la réponse de cptpingu
TychoBrahe 1310 Messages postés samedi 31 janvier 2009Date d'inscription 5 juin 2013 Dernière intervention - 14 juin 2009 à 21:14
0
Merci
«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.
Commenter la réponse de TychoBrahe
cptpingu 3797 Messages postés dimanche 12 décembre 2004Date d'inscription 13 août 2018 Dernière intervention - 14 juin 2009 à 21:20
0
Merci
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 ?
Commenter la réponse de cptpingu
TychoBrahe 1310 Messages postés samedi 31 janvier 2009Date d'inscription 5 juin 2013 Dernière intervention - 14 juin 2009 à 23:20
0
Merci
«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à).
Commenter la réponse de TychoBrahe
cptpingu 3797 Messages postés dimanche 12 décembre 2004Date d'inscription 13 août 2018 Dernière intervention - 14 juin 2009 à 23:33
0
Merci
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.
Commenter la réponse de cptpingu
TychoBrahe 1310 Messages postés samedi 31 janvier 2009Date d'inscription 5 juin 2013 Dernière intervention - 15 juin 2009 à 00:28
0
Merci
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).
Commenter la réponse de TychoBrahe
cptpingu 3797 Messages postés dimanche 12 décembre 2004Date d'inscription 13 août 2018 Dernière intervention - 15 juin 2009 à 00:44
0
Merci
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.
Commenter la réponse de cptpingu
TychoBrahe 1310 Messages postés samedi 31 janvier 2009Date d'inscription 5 juin 2013 Dernière intervention - 15 juin 2009 à 10:21
0
Merci
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.
Commenter la réponse de TychoBrahe

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.