yacc输出意外结果

时间:2017-01-15 23:18:11

标签: c++ c++11 yacc

我在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 >>  : 

1 个答案:

答案 0 :(得分:0)

declareRecordItem内,您创建了stm类型的本地变量std::string,然后返回值:(char*)stm.c_str();

但是,只要stm返回declareRecordItem就不再存在,stm.c_str()返回的指针不再有效。它现在指向的内存很可能被重用来保存其他对象。

因此,如果你想保留字符串的值,你应该

  • 返回std::string本身,依靠RVO提高效率,或
  • 创建并返回动态对象(即new std::string())或
  • 制作字符串缓冲区的C样式副本(即strdup(stm.c_str())

在后两种情况下,您需要在完成后手动释放副本。在第一种情况下,如果需要保留C字符串,仍需要复制底层C字符串。

混合C和C ++字符串处理令人困惑,导致代码混乱。如果您打算使用C ++,我建议您始终使用std::string*,尽管您最终会使用与C样式字符串相同的手动内存管理机制。对于具有符号表的编译器和其他应用程序,一个很好的折衷方案是尽快将字符串放入符号表(或不可变符号名称的映射)中,即使在词法扫描程序中,然后传递对符号的引用(或实习名称)。然后,您可以在编译结束时释放保留字符串的整个存储库。