【问题标题】:passing value from flex to bison将值从 flex 传递给 bison
【发布时间】:2017-04-16 17:03:23
【问题描述】:

我正在尝试打印从 flex 发送的 bison 中的令牌值,但由于某种原因,打印的值在某些情况下是垃圾。

法码:

\".*\" {
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);会给 s1 一个 yytext 的长度。如果我打印 s1 的值,则打印正确,否则最大默认大小为 11,非常短
  • 11 不是字符串的最大大小。字符串的最大大小为std::basic_string::max_size(),比11大很多:ideone.com/7z5oDh

标签: c++ compiler-construction bison flex-lexer bisonc++


【解决方案1】:

以下是未定义的行为:

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;

【讨论】:

  • 如果变量被释放,它是如何对所有长度小于 15 的字符串正常工作并且在休息时失败
  • @JeevansaiJinne:有时未定义的行为会出人意料地做你错误地期望它做的事情。未定义的行为可以是任何东西。
  • 但我尝试了很多字符串,但在 15 之后它才输出垃圾有多精确
  • @JeevansaiJinne:我真的无法在我之前的评论中添加任何内容。您会发现数千个 SO 答案都说同样的话。请阅读Undefined Behaviour:“......调用未定义行为的程序可能会编译和运行产生正确的结果、错误的结果或具有任何其他行为。因此,未定义的行为可能会产生难以检测的错误。”
  • yytextchar*,所以yytext+1 是指向第二个字符的指针。
猜你喜欢
  • 1970-01-01
  • 2012-08-14
  • 1970-01-01
  • 2010-11-14
  • 2011-12-19
  • 1970-01-01
  • 2015-07-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多