[C/C++] pb d'execution

Résolu
ines1 Messages postés 16 Date d'inscription   Statut Membre Dernière intervention   -  
Char Snipeur Messages postés 9813 Date d'inscription   Statut Contributeur Dernière intervention   -
salut, j'ai un probleme en C, j'ai ecris un petit programme qui utilise un enregistrement (struct) de plusieurs personnes et quand je veux affixher ces informations un message d'erreur apparait:

( general protection exception
0x32f7:0x30c9
l8-tp(1) 0x 23f7 : 0x30c9 processor fault )

comment me debarasser de ce message merci .

13 réponses

mamiemando Messages postés 33784 Date d'inscription   Statut Modérateur Dernière intervention   7 885
 
On appelle ça une erreur de fonction. Concrètement tu dois avoir des pointeurs non initalisés ou NULL (avec un malloc par exemple) et du coup quand tu y accèdes ça plante.

LE mieux c'est d'utiliser un débuggeur pour voir où ça plante, ou mettre des printf un peu partout pour localiser la ligne d'erreur. L'idéal ce serait de nous donner ton code.

Bonne chance
0
ines1 Messages postés 16 Date d'inscription   Statut Membre Dernière intervention  
 
salut, je crois que vous avez raison car lorsque j'ai utilisé le debugger l'erreur se situe au niveau de la fonction afficher mais j'ai pas sus remedier a ce probleme. merci


#include <stdio.h>
const x = 20 ;
int n ;

struct stagiaire
{
char* nom;
char* prenom ;
double note ;
char* matiere ;
} ;

struct stagiaire stag[x];
//******************************************************************************
void saisie ()
{
int i;
for (i=1;i<=n;i++)
{
printf ("\n");
printf (" stagiaire n° %i : \n",i);
printf (" donner le nom du stagiaire %i : ",i);
scanf ("%s",&stag[i].nom);
printf (" donner le prenom du stagiaire %i : ",i);
scanf ("%s",&stag[i].prenom);
printf (" donner la note du stagiaire %i : ",i);
scanf ("%lf",&stag[i].note);
int bool ;
int false = 0 ;
int true = 1 ;
bool = false ;
while ( bool == false )
{
if (( stag[i].note < 0 ) || ( stag[i].note > 20 ))
{
printf (" redonner la note du stagiaire %i : ",i) ;
scanf ("%lf",&stag[i].note);
bool = false ;
}
else bool = true ;
}
printf (" donner le module du stagiaire %i : ",i);
scanf ("%s",&stag[i].matiere);
}
}
//******************************************************************************
void afficher ()
{
int i;
printf ("\n");
for (i=1;i<=n;i++)
{
printf ("\n");
printf (" stagiaire n° %i \n",i);
printf (" NOM : %s",stag[i].nom);
printf (" PRENOM %s: ",stag[i].prenom);
printf (" NOTE : %lf",stag[i].note);
printf (" MATIERE : %s",stag[i].matiere);
}
}
//******************************************************************************
void main ()
{
printf ("\n");
printf (" donner le nombre de stagiaires : ");
scanf ("%i",&n);
int choix;
do
{
printf ("\n");
printf (" 1 pour la sisie \n ");
printf (" 2 pour la recherche \n ");
printf (" 3 pour quitter le programme \n ");
printf (" donner votre choix : ");
scanf ("%i",&choix);

switch (choix )
{
case 1 :
{
saisie ();
break ;
}
case 2 :
{
afficher ();
break ;
}
default: break ;
}
} while (choix != 3 );
}
0
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
Salut,

quelques erreurs que j'ai remarqué

const x = 20 ; c'est plutot const int x = 20;

mais ça ne marche pas struct stagiaire stag[x];

en revanche tu peux utiliser
#define NBSTAGIAIRES 20
struct stagiaire stag[NBSTAGIAIRES ]; 
tu utilises des pointeurs mais nul part tu n'alloues pas de la mémoire avec malloc

Voilà ton code (un peu modifier)

si tu choisi 1 tu peut commencer la saisie, tu pourras toujours arrêter la saisie si au lieu de nom tu va taper fin.
A ce moment tu reviendras dans le menu et tu pourras afficher les saisies en utilisant l'option 2

si tu choisi 2 sans avoir faire aucune saisie tu auras un message et le programme se termine
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NBSTAGIAIRES 20 
#define LONG_NOM     50
#define LONG_PRENOM  50
#define LONG_MATIERE 50

/* les prototypes des fonctions */
int saisie(void);
int menu(void);
void affiche(void);
/* fin prototypes */

/* declaration de variables */
char nom[LONG_NOM], prenom[LONG_PRENOM];
char matiere[LONG_MATIERE];
int nb=0;

struct stagiaire
     {
       char* nom;
       char* prenom ;
       double note ;
       char* matiere ;
};
struct stagiaire stag[NBSTAGIAIRES];
/* fin declaration de variables */


int main()
{
  int choix,fin=0;

  choix=menu();
    if (choix == 1)
    {
      fin=saisie();
      if(fin)
        choix=menu();
    }
    if (choix == 2)
      affiche();

  return 0;
}

/* fonction saisie */

int saisie (void)
{
  int i,quitter=0;

  for (i=0;i<NBSTAGIAIRES && (! quitter);i++)
  {
    printf ("\nstagiaire n° %i : \n",i+1);

/* saisie nom */    
    printf ("donner le nom du stagiaire %i ( nom=fin pour quitter) : ",i+1);
    scanf ("%s",nom);
    stag[i].nom =(char *) malloc(strlen(nom) + 1);
    strcpy(stag[i].nom,nom);

    quitter = (strcmp(nom,"fin")==0);
/* quitter le  programme si on a saisi fin
 * sinon continuer */

    if (! quitter)
    {
/* saisie prenom */
      printf ("donner le prenom du stagiaire %i : ",i+1);
      scanf ("%s",prenom);
      stag[i].prenom = (char *) malloc(strlen(prenom)+1);
      strcpy(stag[i].prenom,prenom);

/* saisie note */
      printf ("donner la note du stagiaire %i : ",i+1);
      scanf ("%lf",&stag[i].note);

/* tant que la note est plus petite que 0 
 * ou plus grande que 20 */
      while ( ( stag[i].note < 0 ) || ( stag[i].note > 20 ))
      {
        printf ("redonner la note du stagiaire %i : ",i+1) ;
        scanf ("%lf",&stag[i].note);
      }

/* saisie la matiere */
      printf ("donner le module(matiere) du stagiaire %i : ",i+1);
      scanf("%s",matiere);
      stag[i].matiere=(char *) malloc(strlen(matiere)+1);
      strcpy(stag[i].matiere,matiere);
    }
  }
/* récuperation du nombre de stagiaires saisies */
  nb=--i;
  return quitter;
}

/* fonction menu */

int  menu(void)
{
  int choix;
  printf("\n1. saisie\n2. recherche\n3. quitter\n");
  printf("Faites votre choix : ");
  scanf("%d",&choix);

  return choix;
}

/* fonction affiche */

void affiche(void)
{
  int i;
  if(nb==0)
    printf("Il n'y a pas de stagiaire!\n");
  else
  {
    for(i=0;i<nb;i++)
    {
      printf("Stagiaire numéro %d\n",i+1);
      printf("NOM     : %s\n",stag[i].nom);
      printf("PRENOM  : %s\n",stag[i].prenom);
      printf("NOTE    : %.02f\n",stag[i].note);
      printf("MATIERE : %s\n",stag[i].matiere);
    }
  }
}
0
Char Snipeur Messages postés 9813 Date d'inscription   Statut Contributeur Dernière intervention   1 299
 
Salut.
je trouve que const int x=20;
et stagiaire stag[x]; C'est très bien.
les #define c'est surtout cause d'erreurs.
sinon, je pense que tu ne sais pas qu'en C les tableau commence à 0:
stag[0] est la première donné de stag.
Ensuite, je trouve dangeureux de ne pas corélé la taille de stag et de n.
Si l'utilisateur fourni un n>x tu va avoir des erreur de segmentation.
Soit tu fait une allocation dynamique (le mieux) soit tu limite n à x.
0
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
Salut,

j'ai eu erreur de compilation avec ça
const int x=20;
struct stagiaire stag[x]; 
Enfin j'ai testé pour voir, mais j'ai déjà lu que ce ne sont pas tous les compilateurs qui accepte ça.

Merci.
0

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

Posez votre question
mamiemando Messages postés 33784 Date d'inscription   Statut Modérateur Dernière intervention   7 885
 
Le mieux c'est de faire un tableau que tu alloues avec un malloc. Car le jour ou tu auras plus de 20 stagiaires, que ce soit avec un #define ou avec un const unsigned int, tu seras bon pour recompiler le programme :)
{
  struct stagiare * tab_stagiaire = (struct stagiaire *)malloc(x*sizeof(struct stagiaire));
  //...
  free(tab_stagiaire);
  return 0;
}

Dans un premier temps tu peux mettre la valeur de x en dur dans le programme mais à terme, l'idéal serait de récuperer cette valeur par un scanf ou en regardant les paramètres du main (argv).

Bonne chance
0
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
Salut,

j'attendais ta réponse, pour prendre des notes :-)
j'avance tout doucement

en ce qui concerne l'histoire avec malloc je suis d'accord (à vrai dire j'ai même pensé à le faire, disons que je ne maîtres pas encore :-)) mais j'avance assez rapidement :-)
0
ines1 Messages postés 16 Date d'inscription   Statut Membre Dernière intervention  
 
salut
je vous remercie enoormemnt de m'avoir aider a corriger mes fautes, mais il y a un seul truc que je n'arrive pas a assimiler.

/*
char nom[LONG_NOM], prenom[LONG_PRENOM];
char matiere[LONG_MATIERE];

struct stagiaire
{
char* nom;
char* prenom ;
double note ;
char* matiere ;
};
*/

pourquoi on a declaré "nom" comme etant une chaine de caractere puis on lui a affecter un pointeur on ne pouvais pas faire (char* nom[LONG_NOM] )

merci
0
mamiemando Messages postés 33784 Date d'inscription   Statut Modérateur Dernière intervention   7 885
 
Rappels : allocation statique, allocation dynamique

Il y a deux syntaxes :
1- soit tu utilises un tableau statique de caractère et dont la taille est déterminée à la compilation et donc avant l'exécution :
char buffer[255];

Le tableau est alloué comme une variable classique (genre un int) et est donc désalloué à la fin du scope (la paire d'accolade qui l'englobe) :
{
  int x;
  char buffer[255];
  //...
} // <-- x, buffer sont désalloués

- soit tu utilises un pointeur (une adresse) vers une zone allouée au bon nombre de caractère. Les fonctions malloc et calloc alloue un tel espace et retournent l'adresse de cette plage.
char *str = (char*)malloc(n*sizeof(char));

Le truc c'est que là, la variable locale c'est str, c'est à dire le char * (qui est une adresse) et donc la zone qui est pointée n'est pas désallouée.
C'est donc pour ça qu'il faut faire un jour un free pour libérer la mémoire quand str ne sert plus
{
  char *str = (char*)malloc(n*sizeof(char));
  //...
  free(str); // *str est désalloué ie la plage de n char
} // str est désalloué, mais si on avait pas fait le free *str serait toujours alloué !

A noter que les instructions break, continue, et return désalloue les variables locales de leur scope { }

En ce qui te concerne :
char* nom[LONG_NOM] 

revient à allouer un tableau statique de taille LONG_NOM et pouvant contenir NOM_LONG pointeur char * (c'est donc un tableau d'adresses contenant des adresses invalides).

Bonne chance
0
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
Salut,

c'est vrai que je ne devrais pas faire comme ça

plutôt il fallait que j'écrive
/*
char nom_temp[LONG_NOM], prenom_temp[LONG_PRENOM];
char matiere_temp[LONG_MATIERE];

struct stagiaire
{
char* nom;
char* prenom ;
double note ;
char* matiere ;
};
*/ 


nom
prenom
note
matiere à l'interieur de la structure sont les champs de cette structure

en revanche les
char nom[LONG_NOM], prenom[LONG_PRENOM];
char matiere[LONG_MATIERE];

je les utilise pour allouer la mémoir nécessaire pour les champs de la structure
0
ines1 Messages postés 16 Date d'inscription   Statut Membre Dernière intervention  
 
salut
donc tu veux dire que "nom" et "*nom" ne c'est pas la meme variable, maintenant j'ai compris merci beaucoup pour ton aide.
0
mamiemando Messages postés 33784 Date d'inscription   Statut Modérateur Dernière intervention   7 885
 
char * nom

- nom est de type char * c'est une adresse, le début de la chaîne en fait.
- *nom c'est ce LE char qui est à cette adresse c'est à dire la première lettre.

char nom[255];
char *nom2 = & nom;

nom[i]=*nom+i (ie le caractère à l'adresse nom décalée de 'i' char
En particulier nom[0]=*nom

abcdef   <-- nom[i]
012345  <-- i
|  |-- nom[2], *nom+2
|---- nom[0], *nom
|--adresse : nom


Remarque : quand on lit char * nom on lit
- "(char *) nom" : ie nom est un char *
- "char (*nom) : ie *nom est un char

J'espère que c'est plus clair pour toi
0
ines1 Messages postés 16 Date d'inscription   Statut Membre Dernière intervention  
 
merci beaucoup c'est tres clair maintenant.
0
ines1 Messages postés 16 Date d'inscription   Statut Membre Dernière intervention  
 
salut
j'ai une autre question a propos des chaine de caracteres. par exemple comment fait on pour selectionner juste le premier caractere ou les 2 premiers caracteres du champ "nom" tq "nom" appartient a un tableau d'enregistrements.
merci
0
Char Snipeur Messages postés 9813 Date d'inscription   Statut Contributeur Dernière intervention   1 299
 
Salut.
1-Ton message n'est pas clair
2-La question n'a plus rien à voir avec le sujet d'origine, donc crée s'en un nouveau
3-La réponse me semble donner par mamiemando en <12>
0