Segmentation fault

in libstdc++-6!_ZNKSs7_M_dataEv ()

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Salut à tous,

Je suis en train d'écrire un petit parseur en C++ à l'aide de Flex et Bison (équivalents libres de Lex et Yacc).

J'obtiens une segmentation fault et je n'arrive pas à voir d'où ça vient (gdb m'indique que ça vient de libstdc++6.dll mais ne donne pas plus de détails).

Quelqu'un voit-il la solution ? :)

Voici mon code :

tokens.l

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
%{
#include <string>
#include "ast.h"
#include "parser.hpp"
#define SAVE_TOKEN yylval.string=new std::string(yytext,yyleng)
#define TOKEN(t) (yylval.token=t)
extern "C" int yywrap() { }
%}

%%

[0-9]+                  SAVE_TOKEN; return TOKEN(TNUMBER);
heat                    return TOKEN(THEAT);
on|off                  SAVE_TOKEN; return TOKEN(TSTATE);
target                  return TOKEN(TTARGET);
temperature             return TOKEN(TTEMPERATURE);
\n                      ;
[ \t]+                  ;

%%

parser.y

 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
%{
#include "ast.h"

extern int yylex();
void yyerror(const char *s) { printf("ERROR: %s\n",s); }
%}

%union
{
    std::string *string;
    int token;
}

%token <string> TNUMBER TSTATE
%token <token> THEAT TTARGET TTEMPERATURE

%start commands

%%

commands
    : /*empty*/
    | commands command
    ;

command
    : heat_switch
    | target_set
    ;

heat_switch
    : THEAT TSTATE { printf("%s\n",$2->c_str()); delete $2;}
    ;

target_set
    : TTARGET TTEMPERATURE TNUMBER { std::cout << "Temperature set to " << (*$3) << std::endl; delete $3; }
    ;

%%

ast.h

1
2
3
#include <iostream>
#include <vector>
#include <cstdio>

jess.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include <iostream>
#include "ast.h"
extern FILE* yyin;
extern int yyparse();

int main(int argc,char* argv[])
{
    FILE* input=fopen("test.txt","r");
    yyin=input;
    yyparse();
    fclose(input);
    std::cout << "Done." << std::endl;
    return 0;
}

test.txt

1
2
3
4
5
6
heat on
heat off
heat on
target temperature 23
target temperature 19
heat off

tokens.l est le fichier Flex, parser.y est le fichier Bison, ast.h est vide, jess.cpp est le point d'entrée (main), et le parseur prend en entrée le fichier test.txt.

Dès le parsing de la première commande, j'obtiens un segfault, cela vient de quand j'essaye d'accéder au contenu de string pour l'afficher.

Voici mes commandes de build (je suis sous windows) :

1
2
3
bison -d -o parser.cpp parser.y
flex tokens.l
g++ -g -o jess.exe parser.cpp lex.yy.c jess.cpp

Voici la sortie de gdb :

1
2
3
Program received signal SIGSEGV, Segmentation fault.
0x6fc5e26c in libstdc++-6!_ZNKSs7_M_dataEv ()
    from E:\(...)\MinGW\bin\libstdc++-6.dll

Help ! ^^

+0 -0

Cette réponse a aidé l'auteur du sujet

Pourquoi utiliser des outils préhistoriques quand il y a plus modernes et moins prompt à filer une segfault (boost::spirit par exemple) ?

Sinon, pointeur sur string, c'est dégeulasse et surtout, tu l'alloues quand ? Car ton appel à c_str sur un truc non alloué à toute les chances de faire kabooum

Édité par Davidbrcz

+0 -0
Auteur du sujet

Voilà le backtrace :

1
2
3
4
5
6
7
(gdb) backtrace
#0  0x6fc5e26c in libstdc++-6!_ZNKSs7_M_dataEv ()
   from E:\_Logiciels\Programmation\Logiciels\MinGW\bin\libstd
#1  0x6fc5df93 in libstdc++-6!_ZNKSs5c_strEv ()
   from E:\_Logiciels\Programmation\Logiciels\MinGW\bin\libstd
#2  0x00401734 in yyparse () at parser.y:32
#3  0x00402b32 in main (argc=1, argv=0x6a2f88) at jess.cpp:10

Edit : J'ai commencé à lire la doc de Spirit, comment ai-je pu passer à côté de ça ? :D Tu as raison, je laisse tomber ces vieilleries de Lex et Yacc, je vais faire du vrai C++. Merci pour le tuyau !

Édité par Society

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte