Segmentation fault [Résolu]

Messages postés
20
Date d'inscription
jeudi 21 février 2008
Statut
Membre
Dernière intervention
25 juillet 2010
- - Dernière réponse : SergentP
Messages postés
20
Date d'inscription
jeudi 21 février 2008
Statut
Membre
Dernière intervention
25 juillet 2010
- 25 juil. 2010 à 23:19
Salut à tous,
J'obtiens l'érreur "Segmentation fault" lorsque je compile ce code(lit les lignes d'un fichier et extrait une certaine partie de chacune des lignes):

*********************************************************
const char filename[20] = "servers";
char *tmpstr = NULL;
char buff[40];
char *extension;
FILE * file;
short pos = 0;
short nbligne = 0;
short diff = 0;
short len_tmpstr, len_buff = 0;
bool stop = 0;

file = fopen( filename, "r" );

// nombre de lignes dans le fichier
for (nbligne 0; stop 0; nbligne++)
{
if (fgets( buff, sizeof (buff), file ) == NULL)
{
stop = 1;
printf( "nbligne=%d\n", nbligne );
fclose( file );
}
}

file = fopen( filename, "r" );

for (pos = 0; pos <= nbligne; pos++)
{
if (fgets( buff, sizeof (buff), file ) == NULL) fprintf( stderr, "ERROR fgets() failed: %s\n", strerror( errno ) );

tmpstr = strchr( buff, '|' );
len_tmpstr = strlen( tmpstr );
len_buff = strlen( buff );

diff = len_buff - len_tmpstr;

strncpy( extension, buff, diff );
printf("extension=%s\n", extension);
printf( "tmpstr=%s", tmpstr );
printf( "buff=%s\n", buff );
}
*********************************************************

L'érreur viens apparament de la fonction strncpy() mais je ne comprend pas pourquoi car extension est bien un pointeurs sur des char et buff un tableau de charactères..

Merci d'avance ;)
Afficher la suite 

2 réponses

Meilleure réponse
Messages postés
1310
Date d'inscription
samedi 31 janvier 2009
Statut
Membre
Dernière intervention
5 juin 2013
10
3
Merci
Salut,

Beaucoup d'erreurs dans ton code, en particulier :
- Le type bool n'existe pas en C.
- Ouvrir et parcourir deux fois le fichier est une erreur de conception : une seule fosi est suffisante.
- Juste pour info, au lieux de t'embêter avec fprintf(), strerror() et errno, il existe perror() qui te fais tout ça.
- Autant mettre filename en #define
- Tu as oublié de tester les valeurs de retour de fopen, ce point est très grave.
- Dans la série des fautes graves, fgets() ne termine la chaîne par un \0 que si une nouvelle ligne est lue, ce qui signifie que si ton fichier contient plus de 40 caractères sans retour à al ligne, alors ta chaîne ne sera pas terminée par un \0 et que tes opérations de traitement ne ferons pas du tout ce que tu attend d'elles (segmentation fault, données corrompues, etc). Heureusement pour tout le monde, fgets() ne touche pas au dernier caractère, tu peux donc simplement passer ton buffer à bzero() pour régler le problème.
- Aucun test non plus de la valeur de retour de strchr, comme ça si le caractère n'est pas trouvé tu passe NULL à strlen et c'est partit pour le segfault.
- Enfin passons au strncpy : tu n'as pas alloué d'espace pour extension, c'est un pointeur qui pointe sur n'importe quoi. Forcément, lorsque l'on essaye de copier une chaine de caractère n'importe où, on segfault. Bref, au lieux de le définir en char *extension, fait plutôt un char extension[20] (20 vu que la taille de ton buffer est de 20, il ne sera pas possible de dépasser cette taille).
- Soit dit en passant, 20 comme taille de buffer c'est court, met donc plutôt un truc du genre 1024 à moins que tu soit certain que les lignes de ton fichier ne dépasseront jamais 19 caractères.

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 197 internautes nous ont dit merci ce mois-ci

Commenter la réponse de TychoBrahe
Messages postés
20
Date d'inscription
jeudi 21 février 2008
Statut
Membre
Dernière intervention
25 juillet 2010
0
Merci
* Javais enfait fait un "#include <stdbool.h>"
C'est apparament "considérée comme obsolète" je l'ai donc codé avec des define (pour évité d'avoir à changer tout le code et pour que se soit plus explicite):
#define bool short
#define TRUE 1
#define FALSE 0

* J'ai ouvert 2 fois le fichier pour remettre le pointeur à 0 -> j'ai maintenant fseek( file, 0, SEEK_SET );

* Pour le perror() j'ai pas bien compris comment fonctionnait la fonction -> j'ai plus simplement printf( "ERROR ...() failed: %s\n", strerror(errno) );

* Pour le filename je n'ai meme pas fais de #define mais juste fopen( "servers", "r" ); car je n'est plus qu'un seul fopen()

* Pour ce qui est de la taille des buffer je ne l'ai pas déclaré comme ceci par hasard, je sais que mon fichier (en lecture seule) ne dépasse pas les 32 colonnes (char buff[40]) et pour 'extension' ce sont des extensions de sites internet, qui ne dépasserons donc pas les 19 caractères

* J'ai fais un bzero() au début de la boucle for() sur la variable 'extension' pour éviter les caractères

------------------------------------------------------------

char *tmpstr = NULL;
char buff[40];
char extension[20];
FILE * file;
short pos = 0;
short nbligne = 0;
short diff = 0;
short len_tmpstr, len_buff = 0;
bool stop = 0;

file = fopen( "servers", "r" );
if (file == NULL) printf( "ERROR fopen() failed: %s\n", strerror( errno ) );

// nombre de lignes dans le fichier
for (nbligne 0; stop 0; nbligne++)
{
if (fgets( buff, sizeof (buff), file ) == NULL)
{
stop = 1;
printf( "nbligne=%d\n", nbligne );
}
}

fseek( file, 0, SEEK_SET );

for (pos = 0; pos <= 10; pos++) // mettre nbligne
{
bzero( extension, sizeof (extension) );

if (fgets( buff, sizeof (buff), file ) == NULL) printf( "ERROR fgets() failed: %s\n", strerror( errno ) );

tmpstr = strchr( buff, '|' );
if (tmpstr == NULL)
{
printf( "ERROR strchr() failed: %s / Erreur de syntaxe du fichier 'servers'\n", strerror( errno ) );
break;
}

len_tmpstr = strlen( tmpstr );
len_buff = strlen( buff );

diff = len_buff - len_tmpstr;

strncpy( extension, buff, diff );
printf( "extension=%s\n", extension );
printf( "tmpstr=%s", tmpstr );
printf( "buff=%s\n", buff );
}

fclose(file);
Commenter la réponse de SergentP