2012-10-05 4 views
3

내 String 버전의 코드를 코딩 중이지만 Valgrind는 내 문자열에 << 연산자를 구현 한 것에 대해 우레 소리를 들었습니다. 오류는 에서 잘못된 줄입니다. char로 인쇄 할 경우 큰 효과가 있습니다.조건부 점프 valgrind with char * 및 << 연산자

어디서 잘못 되었나요?

Valgrind의 오류 :

ostream & operator << (ostream & o, String & inS) { 
    o << inS._pData << " "; // the wrong line 
    return o; 
} 

String 클래스 : (char*에 대한)

class String { 
    public: 
     unsigned _size; 
     char * _pData; 
     String(); 
     String(const char* inCString); 
}; 

생성자 :

문자열

==2769== Conditional jump or move depends on uninitialised value(s)

==2769== at 0x4C2AC28: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==2769== by 0x4ECAD60: std::basic_ostream >& std::operator<< >(std::basic_ostream >&, char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17)

==2769== by 0x400BD5: operator<<(std::ostream&, String&) (string.cpp:22)

==2769== by 0x400AAC: main (main.cpp:12)

<< 연산자

String::String(const char* inCString) { 
    _size = strlen(inCString); 
    _pData = new char[_size + 1]; 
    strncpy(_pData, inCString, _size); 
} 

하여 Main.cpp :

int main(int, char**) { 
    String s1("hello"); 
    cout << s1; 
    return 0; 
} 
+2

문자열을 다시 구현해야하는 이유는 무엇입니까? – Benj

+0

[Rule of Three] (http://en.wikipedia.org/wiki/Rule_of_three_ (C % 2B % 2B_programming))에 복종 했습니까? –

+0

@MooingDuck : 그래,하지만 전체 코드는 여기에 없다. 관련된 것만 – bagage

답변

10

은이 같은 원시 문자열을 사용하지 않는 것이 좋습니다. 또는, 수동으로 NUL - 종료 문자를 저장,

strncpy(_pData, inCString, _size+1); 

또는 :

_pData[_size] = 0; 

를 출력 작업이 될 NUL - 종료 문자 누락하여

그러나, 범인은 여기 문자열의 끝에서 계속 실행하십시오. 대신 C API의

  • 경우의

    • 는 C를 사용하는 것을 고려 ++ 스타일 :

      힌트 (문자가 우연히 NUL 될 수 있기 때문에 동작 등 옵션, 컴파일러에 따라, 괜찮보고 발생할 수 있습니다) 당신은 해야 사용 C 스타일 char*, 적어도 사용 stdrup하고, NUL 종료 문자열을하고 주장 쓰는 고려하는 경우

    • free 그 C++도 방법 :

      당신이 당신의 데이터 멤버를 초기화 명시하지
      #include <iostream> 
      #include <vector> 
      
      class String 
      { 
      public: 
          std::vector<char> _data; 
          String(); 
          String(const char* inCString); 
      }; 
      
      std::ostream & operator << (std::ostream & o, String const& inS) 
      { 
          o.write(inS._data.data(), inS._data.size()); 
          return o << ' '; 
      } 
      
      String::String(const char* inCString) 
      { 
          for (const char* it=inCString; it && *it; ++it) 
           _data.push_back(*it); 
      } 
      
      int main(int, char**) 
      { 
          String s1("hello"); 
          std::cout << s1; 
          return 0; 
      } 
      
  • +1

    @cqnqrd 빈 (null-terminated) 문자로'_pData'를 초기화해야합니다) 문자열을 생성자에 넣으십시오. – penelope

    +1

    실제로 char * (학생)을 사용해야하지만 조언을 해주셔서 감사드립니다. – bagage

    -1

    공지 사항, 당신이 그들에 값 할당되어 초기화하기 위해 ...

    을, 당신은 변경해야하는 :

    String::String(const char* inCString) : 
        _size(strlen(inCString)), 
        _pData(new char[_size + 1]) 
    { 
        strncpy(_pData, inCString, _size); 
    } 
    
    +0

    이것은 OP 문제와 관련이 없습니다. –

    +2

    @penelope : 아니에요. int와 포인터는 명시 적으로 생성되지 않으면 초기화되지 않습니다. 즉, C :: C() : m_size(), m_ptr() {}'입니다. – xtofl

    +0

    @penelope, 그것들은 POD 타입이기 때문에 기본 생성자는 호출되지 않습니다. _size 값은 정의되지 않았으며 _pData는 가비지를 가리 킵니다. –

    1

    끝에 0 바이트를 쓰지 않기 때문에. 당신이 필요합니다

    strncpy(_pData, inCString, _size + 1); 
    //        ^^^^ 
    

    당신이해야 항상 read the manual 매우 신중하게 그들 모두가 미묘하게 다른 의미를 갖고 있기 때문에 C 문자열 함수의 n -versions와.

    +0

    오, 나도 복사해야합니다. 조언 주셔서 감사합니다, 나는 지금 조심스럽게 그들을 할 것입니다. – bagage