2012-07-18 1 views
5

다음과 같은 문제가 있습니다. C 라이브러리를 둘러싼 C++ 프로그램을 작성 중이므로 라이브러리와 상호 작용할 때 항상 모든 작업에 std::string 대신 char*을 사용해야합니다. 가능한 한 많은 char* 작업을 피하기 위해, 나는 다음과 같은 예를 들어, stringstream을 가진 서식을 수행 stringstreams로 strdup하면 valgrind 오류가 발생합니다.

#include <iostream> 
#include <sstream> 
#include <string.h> 
#include <cstdlib> 

using namespace std; 

int main(int argc, char** argv) 
{ 
    ostringstream str; 

    str << argv[0] << "+" << "hello"; 

    const char *s = str.str().c_str(); 

    char *y = strdup(s); 

    // this I would give to a library function 

    cout << y << endl; 

    free(y); 

    return 0; 
} 

는 지금까지 출력이가는대로, 프로그램이 제대로 "./test+hello"출력합니다. 그러나 valgrind는 유형의 많은 오류를 제공합니다

==30350== Invalid read of size 1 
==30350== at 0x402B858: __GI_strlen (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==30350== by 0x4213475: strdup (in /usr/lib/libc-2.16.so) 
==30350== by 0x41B2604: (below main) (in /usr/lib/libc-2.16.so) 
==30350== Address 0x4341274 is 12 bytes inside a block of size 25 free'd 
==30350== at 0x4029F8C: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) 
==30350== by 0x410387A: std::string::_Rep::_M_destroy(std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.17) 
==30350== by 0x41B2604: (below main) (in /usr/lib/libc-2.16.so) 

내가 뭘 잘못하고 있니?

답변

6
const char *s = str.str().c_str(); 

str()은 문자열 객체를 반환합니다. c_str을 사용하여 내부 데이터에 대한 포인터를 얻은 다음 줄 끝에서 문자열 객체를 삭제합니다. 하지만 여전히 삭제 된 내부 문자열에 대한 포인터가 있습니다.

당신은 이런 식으로 할 필요가 -

std::string s = str.str(); 
const char* s = s.c_str() 

문자열이 삭제되지 않도록 할 수 있습니다.

+0

'char * y = strdup (str.str(). c_str());'이라고 쓰면 모든 경우에 적용됩니까? –

+0

예, 메모리가 삭제되기 전에 문자열을 복사하고 나중에 포인터의 사본을 보관하지 않으므로 작동합니다. – jcoder

+3

@JonasWielicki 예. 임시의 수명은 전체 표현의 끝까지입니다. (나는 실제로 이와 같은 간결한 표현을 선호하지만 의견은 다양합니다. 불필요한 중간 변수를 많이 사용하고 싶지는 않지만 표현이 너무 복잡해지기를 원하지는 않습니다. 누구에게 물어 보는지) –

관련 문제