2017-01-15 6 views
0

이 규칙은 yacc 파일에 있고 별도의 C++ 파일은 규칙의 동작에 대해 가지고 있습니다. 그러나 출력이 .This 아래의 인쇄 문 같이 예상되지는 parser.y의 규칙입니다 :yacc에서 예기치 않은 결과를 출력합니다.

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

declareRecordItem 내부, 당신은 유형 std::string의 지역 변수 stm을 만든 다음 값을 반환 : (char*)stm.c_str()을;

그러나 declareRecordItem이 반환 되 자마자 stm이 사라지고 포인터가 stm.c_str()에 의해 반환되면 더 이상 유효하지 않습니다. 현재 가리키는 메모리가 다른 객체를 보유하기 위해 재사용되었을 가능성이 큽니다.

그래서 당신은 문자열의 값을 유지하려는 경우, 당신이해야 하나

  • 반환 효율성을 위해 망막 정맥 폐쇄에 의존 std::string 자체, 또는
  • 동적 객체를 생성하고 반환 (예 new std::string()를) 또는
  • 문자열 버퍼의 C 스타일의 사본을 만들어 (즉 strdup(stm.c_str()))
  • 모두 후자의 두 경우

, 당신은 t이 필요합니다 o 복사가 끝나면 복사본을 수동으로 해제하십시오. 첫 번째 경우에는 C 문자열을 유지해야하는 경우 기본 C 문자열의 복사본을 만들어야합니다.

C 및 C++ 문자열 처리를 혼용하면 혼란스럽고 혼란스러운 코드가 발생합니다. C++을 사용하려면 std::string*을 사용하는 것이 좋지만 C 스타일 문자열과 동일한 수동 메모리 관리 체제가 필요합니다. 심볼 테이블이있는 컴파일러 및 기타 응용 프로그램의 경우, 가능한 한 빨리 어휘 스캐너에서 문자열을 심볼 테이블 (또는 불변 심볼 이름의 맵)에 넣은 다음 심볼에 대한 참조를 전달합니다 (또는 인턴 이름). 그런 다음 컴파일이 끝나면 보관 된 문자열의 전체 저장소를 비울 수 있습니다.

+0

동적 객체를 만들면 포인터 유형, 즉 string * stm = new new std :: string(); . 그러나 그것을 루프 내부에 추가하는 방법은 무엇입니까? –

+0

'* stm = * stm + ""+ ...'또는 단지'* stm + = ""+ ...' – rici

+0

마지막 질문 하나주세요. 어떻게 문자열을 char *로 변환 할 수 있습니까? –