2014-07-18 2 views
1

생성자 문자열 (const char * s)이 궁금해서 const char *의 문자가 변경되는 경우가 있습니다. 플래그가 설정된 경우 문자열을 변경하여 어떤 식 으로든 트리를 검색하고 값을 반환하는 간단한 메서드가 있습니다. 문자열 만 사용하면 잘 작동하는 것 같습니다. 그러나 어떤 이상한 이유로 const char *를 다른 함수에서받은 함수로 매개 변수로받은 const char *를 사용할 때가 종종 불완전하게 반환됩니다. 최근까지 내가 찾을 수 없었던 미묘한 오류의 원인은 무엇입니까? 메서드 내에서 다른 문자열을 만들고 문자열 매개 변수를 새 문자열에 추가하면 작동하지만이 방법은 잘못된 방법으로이 문제를 해결할 수 있습니다. 나는 그것이 생성자의 적절한 사용에 대한 오해 일 수 있다고 믿는다. 누군가는이 미묘한 문제에 대해 어떤 통찰력을 가지고 있는가?문자열이 const char *를 매개 변수로 사용하면 변경됩니까

간단한 예로서, 터미널은 아래의 결과를 반환합니다. 불완전한 문자에 대한 기호가 올바르게 복사되지 않고 공백으로 표시됩니다.

enter image description here

편집 : T.C @
.
나는 T.C. 문자열 클래스를 비난하지는 않는다. 나는 이것이 내 오류라는 것을 잘 알고 있으며,이 문제를 이해하려고 시도하고있다. std :: string 클래스에서 생성자를 사용하는 것은 잘못된 해석 일 수 있습니다. 뒷 이야기의 약간은 연습을 위해 C/C++과 java를 함께 사용하고 있습니다. C++에서 최소한의 테스트를 통과 한 클래스를 만들었고 C에서 사용할 수 있도록 래퍼를 만들었습니다. const char 대신 매개 변수로 문자열을 전달하면 문제없이 작동합니다. 그러나 내 이해의 최선을 std :: string이 복사해야합니다 잘 모르겠지만. 저는 사람들이 저에게 C++만을 사용하도록 말할 것이고, 개인이 두 가지를 섞을 때 다른 질문에 대한 답 에서처럼 두 가지를 섞지 말 것을 권할 것입니다. 그러나 어떤 방향으로도 감사 할 것입니다.

원래 질문을 짧게하고 싶었지만 코드를 추가하기 전에 게시했습니다. 첨부 파일은 그 사용법과 이전에 찾을 수 없었던 누락 된 문자 기호의 적절한 그림입니다.

LZW.c (C 급)

... 
const char * tex = Trie_Int_longestPrefix(trie,input); //Find max prefix match tex 
printf("%25s\t",tex); 
//FOR SOME REASON TEX CHANGES AFTER THIS CALL 
arr[size++] = Trie_Int_get(trie,tex); //Add encoding 
printf("%25s\n",tex); 
int t = strlen(tex); 
... 

ctrie.cpp (C-래퍼 클래스)

... 
//Return Value 
int Trie_Int_get(Trie_Int * t,const char * key){return ((Trie<int> *)t)->get(key); } 
... 
//Find and return longest prefix of s in TST 
const char * Trie_Int_longestPrefix(Trie_Int * t,const char * s){return ((Trie<int> *)t)->longestPrefix(s).c_str();} 
... 

Trie.ii (C++ 클래스)

... 
template<typename value> 
value Trie<value>::get(std::string key,const bool & ignoreCase) const { 
    if(key.empty()){throw std::invalid_argument("key must have length >= 1");} 
    if(ignoreCase)__toLowerCase(key); 
    TrieNode* x = get(root,key,0,ignoreCase); 
    return x!=nullptr? x->val : defVal; 
} 
template<typename value> 
std::string Trie<value>::longestPrefix(std::string key,const bool & ignoreCase) const{ 
...Kind of Long 
} 
... 
+5

아마'string'과 모든 것이 코드의 다른 부분과 관련이 없습니다. –

+4

문제가 발생한 코드를 게시하십시오. –

+1

코드에 버그가 있습니다. 버그를 식별하는 데 도움이 필요하면 문제를 재현하는 작은 독립적 인 예제를 게시해야합니다. –

답변

4
template<typename value> 
std::string Trie<value>::longestPrefix(
    std::string key,const bool & ignoreCase) const; 

//Find and return longest prefix of s in TST 
const char * Trie_Int_longestPrefix(Trie_Int * t,const char * s) 
{return ((Trie<int> *)t)->longestPrefix(s).c_str();} 

함수가 클래스 형식을 반환하면 (형식에 대한 참조가 아닌) 직접 calli 그 함수는 그것을 호출하는 완전한 표현의 끝까지 존재하는 임시 클래스 객체를 생성한다.

std::string::c_str()string의 비 const 멤버가 호출 될 때까지 유효한 것으로 보증되는 C 문자열 포인터를 반환하고, 소멸자를 포함하여.

그래서 Trie_Int_longestPrefix 함수는 이미 유효하지 않은 포인터를 반환하며,이를 사용하면 정의되지 않은 동작으로 계산됩니다.

테스트를 실행할 때 잘못된 포인터가 가리키는 메모리에 처음 "인쇄 된"데이터가 포함될 수 있습니다. 하지만 두 번째로 다른 코드는 분명히 그 메모리 영역을 다른 용도로 재사용했습니다.

+0

아, 고맙습니다. 나는 원래 c_str()이 메소드를 떠난 후에 전혀 작동하지 않는 이유에 대해 혼란스러워했다. 그래서 구조체를 사용해 보았지만 단순히 공간을 할당하는 것으로 되돌 렸습니다. 두 가지 방법 모두 조금 어색한 것으로 결정한 이후 그리고 내가 값을 확인했을 때 그 차이를 보지 못했기 때문에 괜찮다고 생각했습니다. 나는 메모리를 할당해야하고 함수 밖에서 메모리를 삭제해야한다는 것을 기억해야한다. – kdgwill

관련 문제