我在yacc文件中有这个规则,并且有一个单独的c ++文件用于规则的操作。 但是输出不是预期的,如下面的print语句所示。这是parser.y中的规则:
RecordItem : IdentifierList ':' TypeDenoter
{
char * result = declareRecordItem ($1 , $3);
$$ = result;
printf(" >>> inside RecordItem >> : %s\n",result);
}
;
这是main.cpp文件中的'declareRecordItem'函数:
char* declareRecordItem( std::vector<char* >* varList , char* type){
string stm = " ";
string identifier;
for(int i=0 ; i < varList-> size() ; i++)
{
identifier= string((*varList)[i]) ;
symtab[identifier] = string(type);
stm = stm + " " + string(type);
}
char * result = (char*)stm.c_str();
printf(">>> inside declareRecordItem >> : %s\n",result);
return result ;
}
declareRecordItem函数中的输出是正确的,但是当它返回到RecordItem规则时,它不会产生任何东西,或者有时会打印出奇怪的符号,如图所示。任何想法!。
>>> inside declareRecordItem >> : i32 i32
>>> inside RecordItem >> :
答案 0 :(得分:0)
在declareRecordItem
内,您创建了stm
类型的本地变量std::string
,然后返回值:(char*)stm.c_str()
;
但是,只要stm
返回declareRecordItem
就不再存在,stm.c_str()
返回的指针不再有效。它现在指向的内存很可能被重用来保存其他对象。
因此,如果你想保留字符串的值,你应该
std::string
本身,依靠RVO提高效率,或new std::string()
)或strdup(stm.c_str())
)在后两种情况下,您需要在完成后手动释放副本。在第一种情况下,如果需要保留C字符串,仍需要复制底层C字符串。
混合C和C ++字符串处理令人困惑,导致代码混乱。如果您打算使用C ++,我建议您始终使用std::string*
,尽管您最终会使用与C样式字符串相同的手动内存管理机制。对于具有符号表的编译器和其他应用程序,一个很好的折衷方案是尽快将字符串放入符号表(或不可变符号名称的映射)中,即使在词法扫描程序中,然后传递对符号的引用(或实习名称)。然后,您可以在编译结束时释放保留字符串的整个存储库。