2012-05-17 3 views
0

std :: cout, std :: stringstream 및 std :: string.c_str()에 문제가 있습니다. 주로 어딘가에 버퍼에 잡히는 내용이있는 것 같아 문제를 해결하는 방법을 모르겠습니다.C++의 StringStream/c_str() 손상

당신에 유래 코드를 읽고 마음에 들지 않으면, 여기 내 GitHub의에 관련 링크는 다음과 같습니다 TLString classTest classthe unit test - 당신은 내보다 간결 질문을 명시 끝으로 건너 뛸 수 있습니다. 여기

Test <std::string> strtest; // A unit test object expecting strings. 
    Test <const char*> chtest; // A unit test object expecting const char*s 
    // ... 

    TurnLeft::Utils::TLString str3("Exterminate."); 
    // ... 

    /* Basically, name() and expect() will use the passed arg. 
    * in the output in order to 
    * display output such as the following: 
    * str(): expecting 'Exterminate.' | Actual 'Exterminate.' => PASS 
    */ 
    strtest.name("str()").expect("Exterminate.").test(str3.str()); 

    /* To try and determine where the corruption was occuring, I did a 
    * simple cout here, and got what should be the expected result of 
    * the next test, 
    * meaning that the actual test should be succeeding. 
    */ 
    std::cout << str3.c_str() << std::endl //outputs Exterminate. normally. 

    /* But when I try to invoke that same method (c_str()) within the test 
    * object, it simply copies the argument passed in for name(). 
    */ 
    chtest.name("c_str()").expect("Exterminate.").test(str3.c_str()); 
    // Should output 'Exterminate.' as in the saatement before, but instead 
    // outputs 'c_str()'. 

는 테스트 클래스의 코드입니다 : 내 단위 테스트에서

, 나는 다음과 같은 코드가

namespace unittest{ 
static std::string status[2] = {"FAIL", "PASS"}; 

    template <class ExpectedResult> 
    class Test 
    { 
    private: 
     ExpectedResult expected; 
     ExpectedResult actual; 
     std::string  testName; 
    public: 
     Test(); 
     Test <ExpectedResult>& expect (ExpectedResult value); 
     Test <ExpectedResult>& name (std::string); 
     void test (ExpectedResult value); 
    }; 

template <class ExpectedResult> Test <ExpectedResult>& 
Test<ExpectedResult>::expect(ExpectedResult value) 
{  
    expected = value; 
    return *this; 
} 

template <class ExpectedResult> 
Test <ExpectedResult>& 
Test<ExpectedResult>::name(std::string aName) 
{ 
    testName = aName; 
    return *this; 
} 

    template <class ExpectedResult> 
    void Test<ExpectedResult>::test(ExpectedResult value) 
    { 
     actual = value; 
     std::cout << testName << ": "; 
     std::cout << "Expecting: " << expected << " | "; 
     std::cout << "Actual: " << actual; 
     std::cout << " => " << status[actual==expected] << std::endl; 
    } 

TLString 클래스는 내가 그 줄 것이다 쓰고 있어요 하나입니다 C++에서 문자열에 대한 좀 더 유동적 인 조작 (예 : 연결). 이 작업을 처리하기 위해 stringstream을 사용합니다. TLStream::c_str() 방법은 정말이 일을한다 : return stream.str().c_str();

그래서, 나는 actualtestName의 값이 할당되는 방법에 대한 정말 혼란 스러워요. 변수에 대한 변수가 상호 작용에 가까워지는 유일한 시간은 둘 다 CLI에 출력 될 때이고 심지어이 경우처럼 두 가지가 다른 데이터 유형 인 경우 충돌이 어디에서 발생하는지 확신 할 수 없습니다.

일부 서드 파티 라이브러리가 C++ 문자열 대신 C 문자열에 의존 할 때를 알기가 쉽기 때문에 c_str() 기능으로 작성했습니다. 그리고 클래스를 제한 할 이유가 없습니다. std :: ios 내에서도, 어떤 것들에는 c 문자열을 사용해야합니다.

도움을 주시면 감사하겠습니다.

감사합니다.

+0

연결에'append' 또는'operator +/operator + ='를 사용하면 무엇이 이상할까요? – chris

+0

필자가 작성한 클래스에서 연산자 + 및 연산자 + =를 구현합니다. 표준 라이브러리 객체로 연산자를 오버로드하는 것이 현명하지 않다고 생각했습니다. 내가 추가하는 다른 기능도 있습니다. 그러나 나는 추가에 대해 몰랐다. 그래서, 그것은 매우 유용합니다. –

+0

Bah, 그 지점에는 모든 수정 사항이 있다고 생각했습니다. 나는 또한 같은 객체에 대한 참조 대신 객체의 복사본을 반환한다는 사실을이 해결하려고 시도하는 동안 발견했습니다. 실제 정의는 Test & name (std :: string)을 읽습니다. 그 변경을 추가하고 커밋하지 않아야합니다. 내 사과. –

답변

4

std::stringstream.str()std::string 임시 개체를 반환합니다. TLStream::c_str()이 반환 될 때이 임시 포인터는 범위를 벗어나 반환 된 char const* 포인터가 해제 된 메모리를 가리키는 상태로 둡니다.

+0

오, 오. 매혹적인. 나는 그 방법을 모두 그저 nix하게 만들 것이라고 생각한다.아주 드문 경우에 C 문자열을 가져와야 할 것입니다. 이중 문자열을 가져 오는 대신 str() 메서드의 반환 문자열 객체에서 호출 할 것입니다. –

0
std::cout << " => " << status[actual==expected] << std::endl; 

==const char*str3.c_str()

그 포인터가 다른를 가리키는 문자열 리터럴 "Exterminate"const char* 포인팅을 비교합니다.

포인터 평등이 아닌 strcmp 같은 것을 사용하여 비교할 필요가 있습니다.

+0

또한 유효하지만, 위의 대답에 따라, 나는 그 메소드를 완전히 제거하고 있습니다. C++ 스트링을 반환하는 것이 더 우아하고, 필요한 경우 c_str() 메소드를 호출하기 때문입니다. –