2012-03-28 1 views
1

한 문자열을 다른 문자열에 추가하려고합니다. 두 개의 전역 문자열 변수 선언 -Valgrind가 string.append (문자열)에 불평합니다.

string grid_filename = "grids/"; 
string rest; 

그런 다음 명령 줄 인수를 가져 오는 함수가 있습니다. 사용자가 명령 줄 인수에 파일 이름을 입력 할 때마다 나머지에 저장해야하며 나머지는 grid_filename에 추가되어야합니다.

==5602== Address 0x45fdc30 is 0 bytes after a block of size 32 alloc'd 
==5602== at 0x402641D: operator new(unsigned int) (vg_replace_malloc.c:255) 
==5602== by 0x43039F7: std::string::_Rep::_S_create(unsigned int, unsigned int,  std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.14) 
==5602== by 0x4304C77: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned int) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.14) 
==5602== by 0x4304DA6: std::string::reserve(unsigned int) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.14) 
==5602== by 0x43053E9: std::string::append(std::string const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.14) 
==5602== by 0x804D5AE: get_command_line_args(int, char**) (main.cpp:74) 
==5602== by 0x804F138: main (main.cpp:244) 

내가 문자열의 두 개의 주소를 출력하고 그 중 어느 것도 하나의 Valgrind의 0 바이트 말하고 일치 - 내 코드를 실행할 때마다

else if(strcmp(temp.substr(0,16).c_str(), "--grid-filename=") == 0) { 
    rest = temp.substr(16,strlen(temp.c_str())-16); 
    grid_filename.append(rest); //line 74! 
} 

지금, Valgrind의 날이 오류를 제공합니다. 내가 여기서 무엇을 놓치고 있니?

grid_filename을 TCP 연결을 통해 문자열을 보내는 다른 함수에 전달했기 때문에이 두 번째 오류가 발생한다고 생각합니다. Valgrind가 말해 줍니 다

==5660== Syscall param socketcall.send(msg) points to unaddressable byte(s) 
==5660== at 0x404A9B1: send (socket.S:64) 
==5660== by 0x804F7C8: main (main.cpp:364) 

누구든지 내게 문제가 무엇인지 설명 할 수 있습니까? 어떤 도움을 주시면 감사하겠습니다. 필요한 경우 코드에 대해 더 많이 제공 할 수 있습니다.

+1

굿! ...... –

+0

첫 번째 오류 메시지가 완료되지 않았습니다. 실제 오류 메시지는 붙여 넣은 텍스트 바로 위에 있어야하며, 0x45fdc30에 읽거나 쓰는 것에 관한 것이어야합니다. 그런 다음 valgrind는 붙여 넣은 메시지를 인쇄합니다.이 메시지는 해당 주소에 대해 알려줍니다. – wolfgang

+0

내가 게시 한 두 번째 오류 메시지는 게시 한 첫 번째 바로 위에 발생합니다. 나는 그들이 분리되어 있다고 생각하여 따로 따로 썼다. 전체 메시지는 "Syscall param socketcall.send (msg)가 주소 지정 불가능한 바이트를 가리키고"다음에 "주소 0x45fdc30은 크기 32 alloc'd 메시지 블록 뒤에 0 바이트가옵니다."로 시작해야합니다. – Sterling

답변

0

첫 번째 오류 : 우리는 valgrind에서 가양 성이있었습니다. 그들이 당신의 코드를 가리키는되지 않습니다 (당신이 실제로 문제가 발생하지 않는 것을 확인했다)

0

참고 특히, 이러한 억제하는 documentation 확인 :이 응답하지 않습니다,이 코드 리뷰 사이트가 아닙니다 ...하지만 난 정말 이걸 응시하고 도망 갈 수 없다.

첫째, 정말 도구 상자에 도움이 일부 기능 :

// Some free functions (because there are too many string types) 
inline char const* c_str(std::string const& s) { return s.c_str(); } 
inline size_t size(std::string const& s) { return s.size(); } 

inline char const* c_str(char const* s) { return s; } 
inline size_t size(char const* s) { return std::strlen(s); } 

template <size_t N> 
char const* c_str(char const (&s)[N]) { return s; } 
template <size_t N> 
size_t size(char const (&s)[N]) { return N - 1; } 

// A helper function (lowest common denominator) 
inline bool beginsWith(char const* big, size_t const bigSize, 
         char const* small, size_t const smallSize) 
{ 
    if (bigSize < smallSize) { return false; } 
    return std::memcmp(big, small, smallSize) == 0; 
} 

// The actual function, doing the adaptation from the various forms of string 
template <typename T, typename U> 
bool beginsWith(T& big, U& small) { 
    return beginsWith(c_str(big), size(big), c_str(small), size(small)); 
} 

// same with endsWith 

을 그리고 당신은 매우 효율적으로 (별도의 메모리 할당) 코드를 다시 작성할 수 있습니다 너무 많은 가독성 :

static std::string const GridFilenameOpt = "--grid-filename="; 

// ... 
else if (beginsWith(temp, GridFilenameOpt)) { 
    grid_filename.append(temp, GridFilenameOpt.size(), std::string::npos); 
} 

오류를 생성하는 코드가 표시되지 않으므로 실제 질문에 많은 도움이되지 않습니다.

+0

'startsWith'를 원한다면'bool startsWith (string const & a, string const & b) {return a.비교 (0, b.length(), b);}'? –

+0

@ JerryCoffin : 나는이 비교를하기 위해 가짜 임시 문자열을 만드는 아이디어를 좋아하지 않는다. 문제는 C++ ('std :: string'과'char const *'와'char const (&) [N]')의 3 개의 문자열 타입의 모든 조합을 열거하는 것이 지루하다는 것입니다. 인터페이스를 가장 낮은 공통 분모에 연결합니다 (실제로 ... 집에서이 통합을 위해'llvm :: StringRef'와 비슷한 클래스를 사용합니다). –

+0

위의 함수는 비교를 위해 새 문자열을 만들어서는 안됩니다. 그것은 단지 비교를위한 시작점과 길이를 지정할 수있는'compare' 멤버 함수를 사용하고 있습니다. 이것은'string'을 위해서만 쓰여지지만, 일반적으로'basic_string'을 일반화하는 것은 간단합니다. 동시에,'memcmp'를 사용하는 것은 그 자체로 꽤 제한적입니다 ... –