Segmentation fault

Résolu
SergentP Messages postés 20 Date d'inscription jeudi 21 février 2008 Statut Membre Dernière intervention 25 juillet 2010 - 23 juil. 2010 à 23:10
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 ;)
A voir également:

2 réponses

TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
24 juil. 2010 à 11:13
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.
3
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
* 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);
0
Rejoignez-nous