2010-01-10 4 views
1

Pourquoi le code suivant indique-t-il une erreur de segmentation?Erreur de segmentation lors de l'utilisation de ferror() dans un programme simple. Pourquoi?

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

int main() 
{ 
    FILE *file; 
    file = fopen("text","r"); 
    if (file == NULL) printf("Error READING FILE"); 
    if (ferror(file)) printf("error reading file"); //line 9 
    return 0; 
} 

Faire en backtrace gdb donne: -

 
> #0 0x00007ffff7ad9d30 in ferror() from /lib/libc.so.6 
> #1 0x00000000004005fa in main() at test.c:9 
+0

pourquoi vous de poursuivre l'exécution après avoir trouvé ce fichier est 'NULL '? – Naveen

Répondre

4

Si fopen renvoie NULL, le fichier n'est pas ouvert; vous passez NULL à ferror, ce qui est invalide. Vous n'avez pas de fichier ouvert à transmettre; c'est ce que NULL signifie, qu'il ne pourrait pas vous donner un pointeur de fichier. ferror est pour obtenir des erreurs liées à la lecture et à l'écriture du fichier, une fois qu'il a été ouvert et que vous avez le fichier pour travailler avec.

Si fopen échoue, et si vous souhaitez obtenir plus d'informations sur la raison, vous devez vérifier le errno global variable, défini dans errno.h.

#include <errno.h> 

// ...snip... 

if (file == NULL) 
    printf("Error READING FILE: %s\n", strerror(errno)); 

Cet exemple montre comment extraire une chaîne décrivant l'erreur; vous pouvez également comparer la valeur de errno avec l'une des valeurs possibles, et faire quelque chose de différent en fonction de l'erreur. Voir le fopen man page, ou le POSIX spec, pour une liste d'erreurs possibles à comparer. Voici comment vous pouvez vérifier contre diverses erreurs possibles:

if (file == NULL) { 
    int error = errno; // copy it so other calls like printf don't modify it 
    printf("Error READING FILE: %s\n", strerror(error)); 
    switch (error) { 
    case EACCESS: 
    // access was denied 
    break; 
    case ENOENT: 
    // the file or one of its ancestors doesn't exist 
    break; 
    // etc... 
    } 
} 

(c'est une extension de quelque chose j'ai écrit dans un commentaire sur une autre réponse)

+0

+1, bonne réponse. Notez que la norme C ne nécessite pas 'fopen' pour définir' errno' (POSIX). Vous devriez mettre 'errno' à 0 avant d'appeler' fopen() '," juste au cas où ". De même, 'errno' peut ou non être une variable globale: c'est une lvalue modifiable, qui peut résulter d'un appel de fonction si la bibliothèque l'implémente comme ça. –

+0

Merci pour la clarification, Alok. J'ai pensé à mentionner que 'errno' n'est pas réellement un global, mais je pense que ce serait plus déroutant qu'éclairant. Je n'étais pas au courant que C ne nécessite pas 'fopen' pour définir' errno'; le plus de code C que j'écris est sous Linux, Mac OS X ou les BSD, donc j'ai tendance à accorder plus d'attention aux pages de manuel, et POSIX, qu'à la norme C. Il est bon de savoir que cette hypothèse n'est pas nécessairement portable. –

+0

Ouais - Je le vois aussi comme une question de qualité d'implémentation - donc il serait difficile de trouver une bonne bibliothèque qui ne spécifie pas d'erreur, en particulier parce que POSIX l'exige. –

7
fichier

est NULL. Vous ne voyez pas le premier printf car le programme se bloque avant que stdout soit vidé.

+2

+1 faisant référence au rinçage du tampon d'E/S. – pilcrow

+0

Quand le stdout est-il réellement vidé? Je veux dire normalement .. –

+0

Si j'ajoute: - fflush (stdout) avant la ligne 9, je reçois la sortie. Mais, juste pour information je veux savoir, quand stdout est-il vidé dans les programmes? –

3

Si le fichier est égal à NULL sur la ligne 9, puis la faille Seg se produira lors de l'appel ferror().

Si le fichier est NULL (tel que déterminé sur la ligne 8), alors vous ne devriez pas effectuer la ligne 9.

Votre code ligne 8 doit être changé en tant que tel:

if (file == NULL) 
{ 
    printf("Error READING FILE"); 
    return 1; 
} 

NB: Je peux me tromper à ce sujet, cela fait un moment que j'ai fait C/C++

+0

Ou modifiez la ligne 9 à 'else if ...'. – kennytm

+0

aussi une autre possibilité –

+0

je pensais ferror() peut être utilisé pour vérifier si le fichier peut être ouvert avec succès. Mais, il est utilisé après l'ouverture du fichier et la vérification d'autres erreurs, le cas échéant .. Ai-je raison? –

Questions connexes