2015-01-03 4 views
1

큰 프로그램에서 작업 중이며 memcpy가 충돌을 일으켰습니다. 나는 작은 프로그램에서 상황을 복제했고 똑같은 일을한다. 나는 어떤 이유로이 프로그램은memcpy로 인해 프로그램이 초기화 된 대상과 충돌을 일으킬 수 있습니다.

// Runs fine 
#include <iostream> 

int main() { 
    char* s1 = "TEST"; // src 
    char* s2; // dest 

    memcpy(s2, s1, strlen(s1) + 1); 
    std::cout << s2 << std::endl; // Should print "TEST" 

    return 0; 
} 

잘 실행 것으로 나타났습니다하지만이 프로그램은 내가 이런 일이 왜 확실하지 않다

// Crashes 
#include <iostream> 

int main() { 
    char* s1 = "TEST"; // src 
    char* s2 = ""; // dest - Note the small change 

    memcpy(s2, s1, strlen(s1) + 1); 
    std::cout << s2 << std::endl; // Should print "TEST" 

    return 0; 
} 

충돌합니다. 누군가가 왜 충돌하는지 설명해 주시겠습니까?

감사합니다.

+0

경우는 C로 코딩 ++ 원시'char *'포인터를 피해서'std :: string'과 C++ 스마트 포인터를 사용해야한다. –

답변

2

두 프로그램 모두 undefined behavior입니다. 그래서 첫번째 것이 충돌하지 않으면 (그것은 초기화되지 않은 포인터를 역 참조합니다!), 그것은 당신이 운이 없다는 것입니다.

대상 (memcpy의 첫 번째 인수)은 할당되고 쓰기 가능한 영역이어야합니다. 어느 로컬 어레이 (또는 아마도 일부 호출자의 프레임 스택에서 로컬 데이터에 어떤 포인터) - 또는 전역 또는 정적 데이터에 어떤 포인터 - :

char arr[32]; 
memcpy (arr, s1, strlen(s1)+1); 

이나 힙 할당 영역 :

char*ptr = malloc(32); 
if (!ptr) { perror("malloc"); exit(EXIT_FAILURE); }; 
memcpy (ptr, s1, strlen(s1)+1); 

일반적으로 "ABC"과 같은 리터럴 문자열은 이 아니고 쓰기 가능입니다. 이들은 읽기 전용 데이터 세그먼트에 있습니다.

위의 코드는 C 코드입니다. C++ 코드를 사용하려면 new을 사용하십시오 (C++에서는 std::string을 사용해야합니다)

참고 : buffer overflows을 피하려면 매우주의하십시오. 이 경우 strlen(s1) 미만 31

+0

도움을 주셔서 감사합니다! 이렇게하면 충돌이 해결되어 결과적으로 다른 버그를 수정하는 데 도움이되었습니다. – Xerif917

2

때문에 위의 코드는 memcpy 오류를 일으키는 이유는 당신이 정의되지 않은 인하는 A 문자열 리터럴가 가리키는 메모리에 s1의 콘텐츠를 복사하려고하는 것입니다 작동 문자열 리터럴은 쓰기가 가능하지 않기 때문에 작동하지 않습니다.

초기화되지 않은 포인터가 가리키는 메모리에 memcpy이 지정되어 있으므로 첫 번째 코드도 잘못되었습니다. 정의되지 않은 동작입니다. 코드의 두 번째 부분은 다음과 같이 수정 될 수

char* s2 = new char[strlen(s1)+1]; 

:

이 같은 new 호출을 추가하여 코드의 첫 번째 부분을 수정할 수

char s2[5] = ""; 
관련 문제