IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

[Segmentation Fault] Interpréteur Interactif


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 17
    Points : 15
    Points
    15
    Par défaut [Segmentation Fault] Interpréteur Interactif
    Bonjour à tous !
    En voulant coder un interpréteur interactif pour le BrainF*ck, je me suis retrouvé face à une segmentation fault.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    /**
     * @file bfw_interactive.cpp
     */
     
    /*
     * IMPORTANT ! 
     * Pour compiler, en sachant que ce fichier est appele bfw_interactive.cpp : 
     * g++ -std=c++0x bfw_interactive.cpp -o bfw_interactive
     */
     
    #include <iostream>
    #include <string>
    #include <stack>
     
    using namespace std;
     
    /// Fonction d'affichage d'aide
    void show_help(char**);
     
    int main(int argc, char *argv[])
    {
    	/* Affichage de l'aide. */
    	if(argv[1] && argv[1][0] == '-' && argv[1][1] == 'h')
    	{
    		show_help(argv);
    		exit(0);
    	}
     
    	/**
             * @param nbr_in_tab  L'indice memoire.
             * @param tab         La memoire.
             * @param code        Le code a entrer.
             * @param nbr_in_code L'indice memoire du code.
             * @param sz1         Pour la sauvegarde dans les boucles.
             * @param sz2         Pour la sauvegarde de sz1.
             * @param addcode     Le code additionnel.
             */
    	int nbr_in_tab = 0;
    	char tab[30000] = {0};
    	string code;
    	int nbr_in_code = 0;
    	int sz1, sz2;
    	string addcode;
    	int nbr_in_tab2 = 0;
    	char tab2[30000] = {0};
    	string code2;
    	string addcode2;
    	int nbr_in_code2 = 0;
     
    	/**
             * @param pos       La pile de position des boucles.
             * @param loopcount Le compte de [ et de ].
             */
    	stack<int> pos;
    	int loopcount = 0;
    	stack<int> pos2;
    	int loopcount2 = 0;
     
     
    	/**
             * @param isComment         Verification des commentaires : true s'il y en a.
             * @param countComment      Nombre de commentaires.
             * @param isNotBeginLoop    Verification des boucles jamais commencees : true s'il y en a.
             * @param countNotBeginLoop Nombre de boucles jamais commencees.
             * @param isNotEndLoop      Verification des boucles jamais finies : true s'il y en a.
             * @param countNotEndLoop   Nombre de boucles jamais finies.
             * @param doExec            La validation du code.
             */
    	bool isComment = false;
    	int countComment = 0;
    	bool isNotBeginLoop = false;
    	int countNotBeginLoop = 0;
    	bool isNotEndLoop = false;
    	int countNotEndLoop = 0;
    	bool doExec = true;
     
    	while(1)
    	{
    		cout << endl << "bfw_interactive> ";
    		getline(cin, code);
    		code2 = code;
     
    		if(code2 == "exit") { exit(0); }
     
    		/* Analyse des boucles et des commentaires avant l'execution du code. */
    		while(nbr_in_code2 != code2.size())
    		{
    			switch(code2[nbr_in_code2])
    			{
    				case '+':
    					tab2[nbr_in_tab2]++;
    					break;
     
    				case '-':
    					tab2[nbr_in_tab2]--;
    					break;
     
    				case '>':
    					nbr_in_tab2++;
    					break;
     
    				case '<':
    					nbr_in_tab2--;
    					break;
     
    				case '.':
    					break;
     
    				case ',':
    					tab2[nbr_in_tab2]++; /* Pour eviter les faux dans les boucles. */
    					break;
     
    				case '[':
    					if(tab2[nbr_in_tab2] == 0)
    					{
    						loopcount2 = 1;
    						do
    						{
    							nbr_in_code2++;
     
    							if(code2[nbr_in_code2] == '[')
    							{
    								loopcount2++;
    							}
     
    							if(code2[nbr_in_code2] == ']')
    							{
    								loopcount2--;
    							}
     
    							if(loopcount2 != 0 && nbr_in_code2 == code2.size())
    							{
    								isNotEndLoop = true;
    								countNotEndLoop = loopcount2;
    								loopcount2 = 0; /* Si il n'y a pas de ] correspondant, on compte le nombre de [ restants, et on ferme la boucle. */
    							}
    						} while(loopcount2);
    					}
    					else
    					{
    						pos2.push(nbr_in_code2);
    					}
    					break;
     
    				case ']':
    					if(pos2.empty())
    					{
    						isNotBeginLoop = true;
    						countNotBeginLoop++; /* Si il n'y a pas de [ correspondant, on compte en memoire qu'il n'y a pas de [ correspondant. */
    					}
    					else
    					{
    						if(tab2[nbr_in_tab2] == 0)
    						{
    							pos2.pop();
    						}
    						else
    						{
    							nbr_in_code2 = pos2.top();
    						}
    					}
    					break;
     
    				default:
    					isComment = true;
    					countComment++;
    					break;
    			}
     
    			nbr_in_code2++;
    		}
     
    		/* Remise a zero. */
    		if(!pos2.empty())
    		{
    			while(!pos2.empty())
    			{
    				pos2.pop();
    			}
    		}
    		nbr_in_code2 = 0;
    		nbr_in_tab2 = 0;
    		tab2 = {0};
    		loopcount2 = 0;
     
    		/* Verification des erreurs. */	
    		if(isNotBeginLoop)
    		{
    			cout << "\tinteractive> " << countNotBeginLoop << " boucle(s) jamais ouverte(s) -> code invalide.";
    			countNotBeginLoop = 0;
    			isNotBeginLoop = false;
    			doExec = false;
    		}
     
    		if(isNotEndLoop)
    		{
    			cout << "\tinteractive> " << countNotEndLoop << "boucle(s) jamais fermee(s) -> code invalide.";
    			countNotEndLoop = 0;
    			isNotEndLoop = false;
    			doExec = false;
    		}
     
    		if(isComment)
    		{
    			cout << "\tinteractive> " << countComment << " commentaire(s) | ";
    			countComment = 0;
    			isComment = false;
    			doExec = true;
    		}
     
    		/* Boucle d'execution du programme. */
    		if(doExec)
    		{
    			while(nbr_in_code != code.size())
    			{
    				switch(code[nbr_in_code])
    				{
    					case '+':
    						tab[nbr_in_tab]++;
    						break;
     
    					case '-':
    						tab[nbr_in_tab]--;
    						break;
     
    					case '>':
    						nbr_in_tab++;
    						break;
     
    					case '<':
    						nbr_in_tab--;
    						break;
     
    					case ',':
    						cin >> tab[nbr_in_tab];
    						break;
     
    					case '.':
    						cout << tab[nbr_in_tab];
    						break;
     
    					case '[':
    						if(tab[nbr_in_tab] == 0)
    						{
    							loopcount = 1;
    							while(loopcount)
    							{
    								if(code[nbr_in_code] == '[')
    								{
    									loopcount++;
    								}
     
    								if(code[nbr_in_code] == ']')
    								{
    									loopcount--;
    								}
     
    								nbr_in_code++;
    							}
    						}
    						else
    						{
    							pos.push(nbr_in_code);
    						}
    						break;
     
    					case ']':
    						if(tab[nbr_in_tab] == 0)
    						{
    							pos.pop();
    						}
    						else
    						{
    							nbr_in_code = pos.top();
    						}
    						break;
    				}
     
    				nbr_in_code++;
    			}
    		}
     
    	}
    }
     
    void show_help(char** argv)
    {
    	cout << argv[0] << " est un interpreteur interactif. Il suffit de taper " << argv[0] << " dans la console, et d'entrer ensuite le code BrainF*ck. Il est fortement deconseille d'utiliser une boucle infinie." << endl;
    }
    En fait, il marche très bien normalement, très bien aussi pour la gestion des commentaires et des boucles non commencées ].
    Mais c'est pour les boucles non terminées que ça se gate.
    Quand je fais ++[+, le cas de la boucle n'est pas traité car la cellule ne vaut pas zéro, donc ça ne segfault pas.
    Mais quand le cas de la boucle à sauter est traité, exemple : >[+++++
    Là j'ai une segmentation fault.

    Quelqu'un pourrait-il m'aider à corriger le code ?

    Merci d'avance !

    !EDIT! : Un p'tit coup de gdb et puis s'en va.
    Apparemment le problème vient de la ligne if(code2[nbr_in_code2] == '['). C'est à cette ligne-là que le programme reçoit un SIGSEGV qui fait crasher le code.
    C'est quand je rentre ça :
    ++>[+
    Quand le code passe au [, nbr_in_code2 vaut 3, puis 4 après son incrémentation. Et là, dès le passage au IF y'a segfault ...
    Je savais pas qu'un IF ferait segfault ...
    Need help !

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Shydow Voir le message
    Bonjour à tous !
    Apparemment le problème vient de la ligne if(code2[nbr_in_code2] == '['). C'est à cette ligne-là que le programme reçoit un SIGSEGV qui fait crasher le code.
    A priori, sans avoir tout regardé, ce qui me semble le plus suspect serait que code2 soit trop petit, et donc que nbr_in_code2 dépasse de la fin du tableau.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 17
    Points : 15
    Points
    15
    Par défaut
    C'est ce que je pensais en fait.
    Ce qui est bizarre c'est qu'avec un autre interpréteur ( non interactif) je n'ai pas cela.

    Et selon gdb, nbr_in_code2 en est à 4 au moment de la segfault. Or 4 c'est la taille de nbr_in_code2 ...

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Shydow Voir le message
    Et selon gdb, nbr_in_code2 en est à 4 au moment de la segfault. Or 4 c'est la taille de nbr_in_code2 ...
    Dans ce cas là, il y a bien un problème, puisque si la taille vaut 4, tu as le droit d'accéder aux éléments 0,1, 2 ou 3.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 17
    Points : 15
    Points
    15
    Par défaut
    4 c'est la taille de code2 je veux dire.
    Puisque le truc entré est :
    ++>[+
    Y'a cinq cases donc le dernier + est à 4, le nombre de nbr_in_code2 au moment du SIGSEGV ...

  6. #6
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    4 c'est la taille de code2 je veux dire.
    Je ne comprends pas ce que tu veux dire là...



    Quand j'essaye ton programme avec VisualC++, en entrant sur la ligne de commande ++>[+ j'ai une erreur sur la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    			switch(code2[nbr_in_code2])
    Car à ce moment code2 contient 5 caractères, et on tente d'en lire le 7ème (nbr_in_code2 vaut 6).
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2009
    Messages : 17
    Points : 15
    Points
    15
    Par défaut
    Ah OK ...
    La boucle finissait pas en fait il fallait mettre while(nbr_in_code2 <= code2.size()) et pas !=.

    Mais du coup ça donne ceci :
    bfw_interactive> ++>[+
    interactive> 1boucle(s) jamais fermee(s) -> code invalide.
    bfw_interactive> ++>]+
    interactive> 1 boucle(s) jamais ouverte(s) -> code invalide. interactive> 1 commentaire(s) |
    bfw_interactive>
    Pourquoi un commentaire ? P-e le \0 final ...

    EDIT : OK, c'est reparti pour un tour ...
    bfw_interactive> +++++]+
    Erreur de segmentation (core dumped)
    $

    RE-EDIT : En fait fallait mettre < au lieu de <=.
    Résolu !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Pb segmentation fault avec glutinit()
    Par pipistrelle dans le forum GLUT
    Réponses: 2
    Dernier message: 17/11/2004, 23h17
  2. [SDL_Image] Img_Load : segmentation fault ....
    Par Mathieu.J dans le forum OpenGL
    Réponses: 6
    Dernier message: 19/10/2004, 23h52
  3. [REDHAT] Segmentation fault systematique
    Par mela dans le forum RedHat / CentOS / Fedora
    Réponses: 2
    Dernier message: 21/09/2004, 06h05
  4. Réponses: 13
    Dernier message: 13/07/2004, 15h41
  5. Comment contrer la "segmentation fault" ?
    Par guillaume_pfr dans le forum C
    Réponses: 15
    Dernier message: 08/08/2003, 13h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo