使用Visual Studiox64在x32中工作时读取参数时,flex / bison解析器代码崩溃

问题描述

我正在尝试移植从flex.bison生成的旧版32位解析器代码。 我必须使用Visual Studio 2019并编译为x64目标。 解析此代码中的参数时,发生崩溃(读取访问冲突):

case 42:

{   registerTypedef( (yyvsp[(2) - (4)]),(yyvsp[(3) - (4)]) ); }
break;

这是调用函数定义:

void registerTypedef(char* typeref,char* typeName)
{
    //SG_TRACE_INFO("registerTypedef %s %s",typeName,typeref);

    std::string typeNameStr = typeName;
    std::string typeRefStr = typeref;
    TheSGFactory::GetInstance().SG_Factory::RegisterTypeDef(typeNameStr,typeRefStr);

相应的规则如下:

declaration_typedef
: TYPEDEF TYPEDEF_NAME IDENTIFIER ';'   {   registerTypedef( $2,$3 ); }
| TYPEDEF basic_type IDENTIFIER ';' {   registerTypedef( $2,$3 ); }
;

似乎使用负索引(2)-(4)= -2。访问了 yyvsp 。 这应该可以,因为同一代码可以与32位编译器完美配合。 C99标准似乎也可以。

我试图使用Windows和UNIX下可用的最新flex / bison版本。生成代码非常相似,而且问题相同。

是否有一个神奇的Visual Studio Option可以使其接受负索引? 是否有一个神奇的Flex / bison参数可以解决此问题?

非常感谢!

解决方法

几乎可以肯定您在错误的位置看

yyvsp始终指向解析器堆栈的 top ,因此负索引是完全正常的。并且完全合法。问题在于,应该是char*的东西不是有效的指针,可能是因为默认语义值类型未从int更改而来。在32位体系结构上,通常可以将指针存储到int中,因为它们的大小可能相同。但是64位编译将中断,因为一半指针将被截断。

如果在启用警告的情况下进行编译,则此错误应该很明显。

请注意,没有什么可以保证YYSTYPE在词法扫描器和解析器中是相同的,因为它们是由不同的代码生成器从不同的源文件生成的独立程序。因此,两者之一或两者都可能是错误的。 (编译器警告将有助于区分情况。)

您最好的选择是确保在YYSTYPE中正确定义了bison生成的头文件,以避免类型不匹配的问题。最简单的方法是使用%define api.value.type野牛声明,但这是一个相对较新的功能。较早的样式是将#define YYSTYPE whatever放在野牛%code requires块中。而且,更老的样式是在YYSTYPE.y文件中都复制.l定义。 (或者通过抑制或忽略编译器警告来“解决”该问题,将问题留给将来的维护程序员使用。:-))

,

我认为这里有两个问题:

  1. @rici对于不同类型的YYSTYPE是正确的:它们必须相同。就我而言,char *

  2. 回调词法分析器代码正在使用strdup()。默认情况下,Visual Studio 2019将此函数解析为返回int的函数。

    yylval = strdup(yytext);

这破坏了堆栈内容 我不得不强制#include 使用posix版本返回char *

注意:我已经需要强制包含,以便其他“ C”功能指向正确的版本(alloca ...)

谜团解决了!非常感谢所有贡献者