Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用$$&引用;PackCC解析器返回的值?_C_Parsing_Packcc - Fatal编程技术网

如何使用$$&引用;PackCC解析器返回的值?

如何使用$$&引用;PackCC解析器返回的值?,c,parsing,packcc,C,Parsing,Packcc,这是一个简单的语法示例 我尝试在解析后检索并打印$$值。单词匹配,但通过printf调用仅显示垃圾 %value "char*" word <- < [a-z]+[\n]* > {$$ = $1;} %% int main(void) { char* val = "Value"; // Create a file to parse. FILE* f = freopen("text.txt"

这是一个简单的语法示例

我尝试在解析后检索并打印
$$
值。单词匹配,但通过
printf
调用仅显示垃圾

%value "char*"

word <- < [a-z]+[\n]* >  {$$ = $1;}

%%

int main(void)
{
    char* val = "Value";
    // Create a file to parse.
    FILE* f = freopen("text.txt", "w", stdin);

    if(f != NULL) {
        // Write the text to parse.
        fprintf(f, "example\n");
        // Set the file in read mode.
        f = freopen("text.txt", "r", stdin);
        pcc_context_t *ctx = pcc_create(NULL);
        // I expect val to receive the "$$" value from the parse.
        while(pcc_parse(ctx, &val));
        printf("val: %s\n",val);
        pcc_destroy(ctx);
        fclose(f);
    }
    else {
        puts("File is NULL");
    }
    return 0;
}
%value“char*”
单词{$$=$1;}
%%
内部主(空)
{
char*val=“Value”;
//创建一个要分析的文件。
文件*f=freopen(“text.txt”,“w”,stdin);
如果(f!=NULL){
//编写要解析的文本。
fprintf(f,“示例\n”);
//将文件设置为读取模式。
f=freopen(“text.txt”,“r”,stdin);
pcc\u context\u t*ctx=pcc\u create(空);
//我希望val从解析中接收“$$”值。
while(pcc_parse(ctx,&val));
printf(“val:%s\n”,val);
pcc_销毁(ctx);
fclose(f);
}
否则{
puts(“文件为空”);
}
返回0;
}
PackCC文件指出,
$$
是:

将规则结果存储到的输出变量

它说,
pcc\u parse
函数:

解析输入文本(默认情况下来自标准输入),并在
ret
中返回结果。如果不需要输出数据,
ret
可以是
NULL
。如果没有要分析的文本,则此函数返回0,否则返回非0值


使用
$$
没有问题,因为
word
操作存储在
$$
中的
char*
值被忠实地返回到
val

问题在于
char*
值是指向动态分配内存的指针,当解析器返回动态分配的内存时,该内存已经被释放。因此,返回到
val
的指针是一个悬空指针,在调用
printf
时,内存区域已用于其他对象

PackCC的文档(比如它)没有详细介绍它的内存管理策略,因此不清楚规则中的
$1
指针的有效时间。我认为最保险的假设是,它只在规则中最后一个动作结束之前有效。但是,假设指针将在调用
pcc\u parse
后持续时间更长,这显然是不合理的。毕竟,解析器无法知道您已将指针存储在解析器上下文之外。解析器不能依赖程序员来
释放
捕获规则期间生成的字符串;必须
免费
每次捕获,即使是从未使用过的捕获,都会带来极大的不便。为了避免内存泄漏,解析器因此必须
释放其捕获缓冲区

问题很容易看出,您是否能够使用或使用类似的工具。(自v10.9.X以来,Valgrind可用于大多数Linux发行版和OS X。可能支持其他平台。)在Valgrind下运行解析器会生成以下错误报告(截断):

$valgrind--leak check=full./test3
==2763==Memcheck,内存错误检测器
==2763==2002-2017年版权(C)和GNU GPL'd,朱利安·苏厄德等人。
==2763==使用Valgrind-3.13.0和LibVEX;使用-h重新运行以获取版权信息
==2763==命令:./test3
==2763== 
==2763==大小为1的读取无效
==2763==at 0x4C34CF2:strlen(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)
==2763==0x4E9B5D2:vfprintf(vfprintf.c:1643)
==2763==0x4F7017B:uu printf_chk(printf_chk.c:35)
==2763==0x10A32D:printf(stdio2.h:104)
==2763==0x10A32D:main(test3.c:1013)
==2763==地址0x5232e20是大小为9的块中的0字节
==2763==at 0x4C32D3B:空闲(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)
==2763==0x109498:pcc捕捉表项(test3.c:339)
==2763==0x1096E3:pcc\u thunk\u chunk\u destroy(test3.c:441)
==2763==0x10974F:pcc\u lr\u answer\u destroy(test3.c:557)
==2763==0x109818:pcc\u lr\u memo\u map\u术语(test3.c:602)
==2763==0x10985F:pcc\u lr\u表项\u销毁(test3.c:619)
==2763==0x109BB8:pcc\u lr\u table\u移位(test3.c:680)
==2763==0x109C1C:pcc\u提交\u缓冲区(test3.c:757)
==2763==0x10A22C:pcc_解析(test3.c:986)
==2763==by0x10A314:main(test3.c:1011)
==2763==Block在
==2763==0x4C31B0F:malloc(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)
==2763==0x108C9D:pcc_malloc_e(test3.c:225)
==2763==0x108FF3:pcc\u strndup\u e(test3.c:252)
==2763==by 0x109038:pcc\u get\u capture\u字符串(test3.c:764)
==2763==0x10904E:pcc\u action\u word\u 0(test3.c:892)
==2763==0x108C56:pcc_do_动作(test3.c:872)
==2763==0x108C87:pcc_do_行动(test3.c:875)
==2763==by0x10A224:pcc_解析(test3.c:983)
==2763==by0x10A314:main(test3.c:1011)
这需要经历很多,但它表明有人试图使用9字节动态分配内存区域的第一个字节,该内存区域已经空闲。(“地址0x5232e20是大小为9 free'd的块中的0字节”。)此外,回溯显示错误是由调用
strlen
触发的,该调用由
printf
调用<已从
main
函数调用code>printf
。(不幸的是,PackCC没有发出
#line
指令,因此无法将生成的C解析器中的行号与原始PEG语法文件中的行号相关联。但是,在这种情况下,很清楚
printf
在哪里,因为在
main
函数中实际上只有一种可能性。)Valgrind还向您展示了动态分配内存的位置;虽然您必须手头有一份生成的解析器的副本,以查看所有部分如何组合在一起,但调用跟踪中的函数名称有些帮助

解决方案基本上与必须在解析器中处理
yytext
的方式相同
word <- < [a-z]+[\n]* >  {$$ = strdup($1);}