在Bison/Flex中释放内存的位置
Where to free memory in Bison/Flex?
我用的是Bison &Flex 1个月或多或少,所以我很抱歉,如果我没有看到一些明显的东西(但我不认为是)。
我有一个关于Flex Bison释放内存的问题。下面是我的代码:
parser.l
{DATE} { yylval.str= strdup(yytext);
pair<string,string> newpair = make_pair("DATE",yytext);
myvector.push_back(newpair);
return TOKEN_DATE ;}
这是我的。l文件的一个例子。我将yytext的值复制到yylval.str中。然后用该内容创建一个新对(实际上是键/值),然后返回bison的令牌日期。我的解析器。y不超过yyparse;当某些内容被捕获时,它只是打印它。
我试着在这个上运行valgrind,我有多个关于strdup的错误。我知道这个函数使用malloc,但我不知道在哪里和什么时候使用FREE。
我可能猜它在。y文件中,但是在哪里?
test:
TOKEN_DATE { cout << $1 << endl; // here ? and what to free ?}
我不太明白这些,我希望能有一个简单明了的解释。
提前感谢,
编辑:
我尝试了以下几种方法:
test:
TOKEN_DATE TOKEN_TOTO TOKEN_BLABLA { cout << $1 << endl; free($1); free($2);}
| TOKEN_DATE test { cout << $1 << endl, free($1); }
它似乎编译和执行良好,但valgrind仍然告诉我,strdup函数中包含的malloc有问题。但是我不能在flex文件中写free(yylval.str),否则,bison将不知道这个值(如果我理解正确,我试过了,它不起作用)。我真的不知道如何消除这个泄漏问题。
当您不再需要复制的字符串时,您需要释放它。在比较简单的情况下,您可以在打印出来之后释放($1),但通常情况下,解析器将复制的字符串插入到某些数据结构中,在这种情况下,该数据结构成为malloc存储的所有者,并且对free的调用将在析构函数中执行。
这与其他资源管理问题没有什么不同;您需要始终清楚谁是已分配资源的所有者,因为所有者有责任在不再需要资源时释放资源。
内部发生的事情是bison
维护一个语义值堆栈,每个语义值都具有类型YYSTYPE
(即。"语义型"),这也是yylval
的类型。当一个令牌被移到堆栈上时,bison
将yylval
复制到堆栈的顶部。在执行产品对应的动作之前,bison
将产品中每个终端和非终端的语义值称为$1
, $2
等。各种$x
符号被替换为对bison
堆栈位置的引用。
非终结符也有语义值,因为每个操作将一个值存储到伪变量$$
中。(如果动作不这样做,则$$
的值是不可预测的,但它仍然存在。)动作完成后,bison移除$1
, $2
…然后将伪变量$$
复制到堆栈的顶部。它不会对弹出的值做任何事情,所以如果它们需要被释放或以其他方式销毁,操作必须自己完成。
因为语义值是简单复制的,所以语义类型不应该包含任何不能简单复制的c++对象。
如果使用%union
声明,则语义类型YYSTYPE
是union
对象,并且需要告诉bison
哪个联合标记适用于每个终端和非终端。在这种情况下,$$
和所有$n
都自动添加了正确的.tag
,并且操作在某种程度上变得更加类型安全。
从flex手册:
21.3关于yytext And Memory的说明
当flex找到匹配时,yytext指向在输入缓冲区中匹配。字符串本身是输入的一部分缓冲区,而不是单独分配。yytext的值将为下次调用yylex()时覆盖。简而言之,价值Yytext只在匹配规则的操作中有效。
因此make_pair不应该是如下的吗?
pair<string,string> newpair = make_pair("DATE",yylval.str);
如果是,那么在清理pair内存时应该释放该字符串。
简单的回答是:看情况。当你用完内存后,你应该释放它,无论何时。
更有用的答案:尝试使用尽可能少的内存分配。如果你从来没有malloc
任何内存,你从来没有free
任何内存。在你给出的例子中,你对一个日期进行模式匹配。通常,日期有一定的格式和长度上限;例如,格式'yyyy/mm/dd'包含10个字符。如果您能够预料到这一点,那么您可以简单地将一个静态大小的字符数组放入yylval
,例如char date[10];
,而不是创建一个新的字符串来保存日期。
- 你好。。。id_public变量不应该给出结果为 81 和 86 吗?为什么它为两个派生类占用不同的内存位置?
- 如何在不等待检索的情况下获取C++中的内存位置?
- 向量的内存位置不连续
- 如何根据C++在同一内存位置重新初始化 C# 中的对象(还是自动完成)?
- 常量引用的内存位置
- C++强制变量到一个固定的内存位置
- 为什么未初始化的内存位置的值给出 -842150451 的值?
- 为什么存储在内存位置的值会发生变化?
- 在特定内存位置构造 c++ 对象
- 如果不初始化结构中的向量,它会自动为空还是具有随机内存位置的值?
- 内存位置出现Microsoft C++异常:std::out_of_range
- 函数,返回变量c++占用的内存位置的大小
- 无法在 Opencv 中显示图像导致内存位置
- 从十六进制到双的转换始终导致内存位置的 std::out_of_range
- 错误 在测试.exe 0x76C9FD62时出现未经处理的异常:Microsoft C++异常:内存位置0x006FF8
- 错误:内存位置的 std::length_error
- C++不同内存位置中的默认数组值
- 为什么动态分配的两个变量的内存位置不是连续的?
- Boost.进程间内存位置
- 查找编译时构造类的内存位置