Я пытаюсь напечатать значение токена в бизоне, отправленном с flex, но по какой-то причине напечатанное значение является мусором в некоторых случаях.
лекс код:
\".*\" {
std::string* s1 = new std::string(yytext);
std::string s2 = *s1;
std::string s3 = s2.substr(1,s2.size() - 2);
yylval.s = &s3;
return VARIABLE;
}
код бизона:
%union{
std::string *s;
};
%type <s> expr
expr : VARIABLE { caps($1); }
void caps(std::string *str){
std::string str1 = *str;
for(std::string::size_type i=0;i<str1.length();i++)
std::cout << str1[i];
}
Если я ввожу строку длиной менее 15 символов, она выводит нормально, но если длина выходит за ее пределы, выводится мусор.
Если я изолирую код C ++ и запускаю его нормально, я не понимаю, почему это происходит, поэтому кто-то может найти в нем ошибку.
Следующее является неопределенным поведением:
std::string* s1 = new std::string(yytext);
std::string s2 = *s1;
std::string s3 = s2.substr(1,s2.size() - 2);
yylval.s = &s3;
return VARIABLE;
s3
является локальной переменной, но вы пытаетесь вернуть указатель на нее. поскольку s3
будет разрушен, как только return
оператор выполняется, указатель будет оставлен в незанятой памяти, и попытка использовать его позже будет иметь непредсказуемые последствия.
В любом случае последовательность не нужна. Flex устанавливает переменную yyleng
на длину токена, так что вы можете просто использовать это для создания строки, которую вы действительно хотите:
yylval.s = new std::string(yytext + 1, yyleng - 2);
return VARIABLE;
Других решений пока нет …