2009-12-07 3 views
3

I이 간단한 함수 가지고 그 함수의 둘째 줄에.c_str() 이상한가요? 운율이나 이유없이 데이터가 변경 되었습니까?

const wchar_t *StringManager::GetWCharTStar(int stringId) 
{ 
    std::wstring originalString = StringManager::GetString(stringId); 
    const wchar_t *retStr = originalString.c_str(); 
    return retStr; 
} 

를 I *이 올바른 wchar_t가있다. 그러나 돌아가려면 데이터가 가비지 데이터로 전환됩니다. 사이에 기능이 없습니다. 무엇을 준다?!

답변

11

originalString이 스택에 할당됩니다. .c_str() 메서드는 wstring 객체의 연속적인 내부 메모리에 대한 포인터를 반환합니다. 함수가 돌아 오면 originalString은 범위를 벗어나서 소멸됩니다. 따라서 반환 한 포인터 값은 삭제 된 메모리를 가리 킵니다.)이 메모리를이 작업을 수행해야하는 경우

, 당신은 당신이 (새로운 또는 malloc을 함께 할당 메모리에 데이터의 복사본을)해야하고 호출자는 (무료/삭제해야합니다.

+0

감사합니다. –

+3

"새로운 또는 malloc()"으로 할당 한 메모리에 데이터 복사본을 만들어야합니다. 글쎄, 당신은 값으로 wstring을 돌려줘야하고, 호출자는 이것을 사용하도록 바꿔야합니다. 만약 오우거가 밤중에 침입하여 그 코드를 먹고, 다시 한번 그렇게 생각한다면 먹을 것을 위협합니다. 그러면 동적 할당을 고려할 수 있습니다 ;-) –

+0

@steve : 네, 맞습니다. 이것이 내가 "당신이해야한다면,"미묘한 것으로 시작한 이유입니다. –

5

임시 포인터를 반환하고 있습니다. originalString이 범위를 벗어나면 포인터가 가리키는 데이터가 삭제됩니다.

0

FAQ입니다. 실제로 사용하기 전에 해제 된 객체 (originalString 객체)에 대한 포인터를 반환합니다.

3

std::wstring originalString;GetWCharTStar 기능 체내 국소 변수이다.

은 즉시 당신이 GetWCharTStar() 기능의 범위를 떠나,이 지역 변수는 파괴되지 도착하고 돌아 포인터가 더 이상 유효합니다.

다음 코드는 결국 작동 할 수 있습니다 : 참조 반환 StringManager::GetString() 제공

const wchar_t *StringManager::GetWCharTStar(int stringId) 
{ 
    const std::wstring& originalString = StringManager::GetString(stringId); 
    const wchar_t *retStr = originalString.c_str(); 
    return retStr; 
} 

그러나

const std::wstring& StringManager::GetString(int stringId); 

을, 이것은 여전히 ​​위험은 결코됩니다 StringManager 클래스에 의해 관리되는 문자열을 가정으로 기억에서 재배치. 예를 들어, StringManagerstd::vector의 도움으로 구현 된 경우 벡터를 확장해야하는 즉시 이전 내용이 더 큰 메모리 블록의 다른 곳으로 복사되고 더 이상 존재하지 않는 객체에 대한 참조가 유지됩니다.

즉, avoid returning handles to internal data입니다.

1

하나의 작은 세부 사항을 제외하고 이전 답변은 대부분 정확합니다. 파괴 된 객체에 포인터를 반환하지 않으면 파괴 된 객체에 의해 소유의 포인터이 반환됩니다. 그 물체가 파괴되었을 때, 당신이 가리키고 있던 물체도 파괴되었습니다.

+1

포인터 자체는 객체가 소유하지 않습니다. 포인터가 가리키는 데이터는 객체가 소유합니다. –

관련 문제