Windows Bison解析器的执行根据输入文件的大小而终止
我使用bison创建了一个解析器,并使用flex创建了一个scanner来解析windows中的setupapi.log文件。我试着通过提取文件的一小部分来执行解析器,它成功了。对于大约20行的文件来说,它工作得很好。但是,当我在正文的最后一行添加了两个字时,它在那里终止了,因为.exe已经停止工作,所以出现了错误 我怎样才能摆脱这个 我在bison文件中使用%union,每当遇到标识符时,都使用flex文件中的malloc分配内存 我的flex文件是:Windows Bison解析器的执行根据输入文件的大小而终止,windows,bison,filesize,terminate,Windows,Bison,Filesize,Terminate,我使用bison创建了一个解析器,并使用flex创建了一个scanner来解析windows中的setupapi.log文件。我试着通过提取文件的一小部分来执行解析器,它成功了。对于大约20行的文件来说,它工作得很好。但是,当我在正文的最后一行添加了两个字时,它在那里终止了,因为.exe已经停止工作,所以出现了错误 我怎样才能摆脱这个 我在bison文件中使用%union,每当遇到标识符时,都使用flex文件中的malloc分配内存 我的flex文件是: %{ #include <s
%{
#include <stdio.h>
#include "check.tab.h"
#include <string.h>
#include<malloc.h>
int yyline=1;
int i;
%}
identifier [_a-zA-Z\.0-9:=&\\{}()\'\-]+
time ([0-9]+\:[0-9]+\:[0-9]+\.[0-9]+)
%%
"/" {
return(SLASH_TOK);
}
"[" {
return(OPEN_TOK);
}
"]" {
return(CLOSE_TOK);
}
">>>" {
return (START_TOK);
}
"<<<" {
return (END_TOK);
}
"!!!" {
return(ERROR_TOK);
}
"!" {
return(WARN_TOK);
}
"...:" {
return(VEND_INFO);
}
"bak:" {
return(BAK_TOK);
}
"cci:" {
return(CCI_TOK);
}
//SOME MORE TOKENS ARE HERE....
"\n" {
yyline++;
}
{time} {
yylval.sval = malloc(strlen(yytext)+1);
printf("FRM LEXER TIME= %s %s\n",yytext,yylval.sval);
strncpy(yylval.sval,yytext,strlen(yytext)+1);
for(i=0;yylval.sval[i]!='\0';i++)
{
if(!(i<strlen(yytext)))
{
yylval.sval[i]='\0';
}
}
printf("FRM LEXER TIME= %s %s\n",yytext,yylval.sval);
return(TIME);
}
[a-zA-Z_0-9:\\]+(\.)+[\.a-zA-Z_0-9:\\]* {printf("REACHED EXTRA\n");return(DATA);}
[a-zA-Z]+(\:)+[\.a-zA-Z_0-9:\\]* {yylval.sval = malloc(strlen(yytext)+1);
strncpy(yylval.sval,yytext,strlen(yytext)+1);
printf("REACHED EXTRA\n");
for(i=0;yylval.sval[i]!='\0';i++)
{
if(!(i<strlen(yytext)))
{
yylval.sval[i]='\0';
}
}
return(DATA);
}
{identifier} {
yylval.sval = malloc(strlen(yytext)+1);
strncpy(yylval.sval,yytext,strlen(yytext)+1);
//printf("YYTEXT=%s %d\n",yytext,strlen(yytext));
for(i=0;yylval.sval[i]!='\0';i++)
{
if(!(i<strlen(yytext)))
{
yylval.sval[i]='\0';
}
}
printf("FRM LEXER ID = %s %s\n",yytext,yylval.sval);
return(IDENTIFIER);
}
%%
int yywrap(void)
{
return 1;
}
%{
#包括
#包括“检查选项卡h”
#包括
#包括
int-yyline=1;
int i;
%}
标识符[\u a-zA-Z\.0-9:=&\\{}()\'\-]+
时间([0-9]+\:[0-9]+\:[0-9]+\.[0-9]+)
%%
"/" {
返回(SLASH_-TOK);
}
"[" {
返回(打开_-TOK);
}
"]" {
返回(关闭_-TOK);
}
">>>" {
返回(启动_-TOK);
}
“来自strcat手册页(也应适用于Windows):
函数的作用是:将src字符串附加到dest字符串,
覆盖dest末尾的空字节('\0'),然后
添加一个终止的空字节。字符串
可能不重叠,并且dest字符串必须有足够的空间用于结果
现在你正在做:
statements : word
{
$$=$1;
printf("STAETEMENT 1\n");
}
|statements word
{
$$=$1;
strcat($$," ");
strcat($$,$2);
printf("statements 2\n");
}
;
因此,如果我假设您得到两个单词的输入,则会发生以下情况:
在第一个单词之后,语句指向这个单词,因为您确实使用了$$=$1
。
然后你的扫描器读取下一个单词,你将一个空格和下一个单词连接到第一个单词。但是你没有注意可用内存。
你正在用C语言编程,这意味着你必须自己做所有的事情
您可以将第二个操作更改为:
statements : statements word
{
int lgth1 = strlen($$);
int lgth2 = strlen($2);
/* instead of malloc you could also realloc */
char *tmp = (char *) malloc((lgth1 + lgth2 + 1 + 1) * sizeof(char));
/* no error handling for clarity */
sprintf(tmp, "%s %s", $$, $2); /* alternative: strcpy(); strcat(); strcat(); */
free($$); free($2); /* freeing the memory not used any more */
$$ = tmp;
}
这当然不是防弹代码,您还必须修复其他地方。
希望这能有所帮助。简化程序并给我们一些代码如何?在简化的过程中,注意错误消失的地方。这可能会给你一个问题原因的线索。你的malloc不会为后面的NUL留下空间。使用snprintf
而不是sprintf。调用两次:第一次使用长度为0的值来获得第二次e需要长度,在malloc'ing足够的存储空间后第二次使用该长度。感谢您指出。我错过了“”实际上,不是\0,但效果是一样的。我认为snprintf()的开销比strlen()大两倍,但优点是不会忘记计算空格字符(或添加任何字符)。我将交替编辑代码,使用常用的非标准GNU/BSDasprintf
函数,操作将变成{asprintf(&$$,%s%s',$1,$2);free($1);free($2);}
永不老学:-),并感谢您的第二次更正
statements : statements word
{
int lgth1 = strlen($$);
int lgth2 = strlen($2);
/* instead of malloc you could also realloc */
char *tmp = (char *) malloc((lgth1 + lgth2 + 1 + 1) * sizeof(char));
/* no error handling for clarity */
sprintf(tmp, "%s %s", $$, $2); /* alternative: strcpy(); strcat(); strcat(); */
free($$); free($2); /* freeing the memory not used any more */
$$ = tmp;
}