메뉴 건너뛰기


Developer > Application

C,C++ memcpy()와 memmove()의 차이

2013.12.28 03:10

푸우 조회 수:17591

제가 얼마전 C로 C++의 STL  Vector와 유사한 기능을 갖는 함수들을 만들었습니다. 그 중 insert_at()과 insert()기능을 구현하면서 개인적으로는 좀 황당한 일을 겪었는데... (여러분들은 황당하지 않았을 수도 있음. ^^;) 그에 대한 이야기를 적어 봅니다.
 
간단하게 설명하기 위해 10개의 문자열 한가운데 글자를 하나 집어 넣는 예로 설명해 보겠습니다.
이 기능을 구현하기 위해서 어떻게 할 까 고민하다가...
for문을 돌리느리 포인터 계산을 해서 memcpy()로 한방에 가운데 이후 글자들을 뒤로 밀고...
여유가 생긴 가운데에 글자를 집어 넣어야 겠다고 생각했습니다.
그래서 다음과 유사한 로직의 코드를 구현하였죠.
 
#include <stdio.h> #include <memory.h> int main(int argc, char *argv[]) { char buf[12]="1234567890"; memcpy(buf+6, buf+5, 6); buf[5]='A'; printf("%s\n", buf); return 0; }
 
코드가 좀 어색해 보일지는 몰라도 저의 생각은 명료했고 실제로도 잘돌아 가더군요.
꼼꼼하게(?) 문자열 마지막 NULL까지 복사하기 위해 6바이트를 복사했죠.
출력된 결과는 이미 예상하셨겠지만 다음과 같습니다.
 
12345A67890
 
컴파일러는 VC2005를 사용했습니다. 그래서 Vector기능을 다 만들고 잘 쓰고 있었는데...
어떤 사정에 의해 같은 소스를 VC6.0에서 컴파일을 하게 되었습니다.
소스를 수정하지도 않았고 Vector를 한동안 잘 썼었터라 테스트 하지도 않고 사람들에게 나눠줬습니다.
 
그런데... 잘쓰던 Vector에서 버그 리포팅이 된겁니다.
그래서 VC6.0에서 디버깅을 했는데... 저는 역시나 잘돌아가는 겁니다.
이리저리 테스트해보다가 문제가 생기는 시점을 찾았는데...
디버그 모드로 컴파일했을때는 생각대로 잘 돌아가는데... 릴리즈로 컴파일했을때 이상한 결과를 출력하더군요. 
릴리즈 모드에서의 결과는 다음과 같았습니다.
 
12345A67899
 
즉, 현상이 VC2005에서는 디버그와 릴리지 모드 모두 생각대로 잘 되었구요. VC6.0에서는 디버그 모드에서만 정상적으로 처리되었던 겁니다.
한참을 고민했습니다. 내가 틀렸을까? VC6.0 컴파일러의 문제일까? 하구요.
 
그래서 도움말을 살펴보기 시작했는데... 이미 제목에서 아셨겠지만...
답은 memmove()에 있었습니다.
 
즉, memcpy()와 memmove()는 유사한 기능을 하는데...
한가지 차이점은 메모리 복사시 Ovelap된 영역의 메모리를 memmove()는 보장해 주지만... memcopy()는 그것에 대해 아무 정의도 되어 있지 않았는다는 겁니다.
결국 제가 잘못한거지만... 변명을 한다면 안될려면 일괄적으로 안되던지... 어떤때는 되다가 안되다가 하니깐... 영~
 
아무튼 다음과 같은 소스를 만들어서 테스트를 해보았습니다. 이번에는 모두 VC6.0에서 릴리즈 모드로 컴파일 해서...
 
 
#include <stdio.h> #include <memory.h> int main(int argc, char *argv[]) { char temp[102]="ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ"; char buf[1020]= "11111111111111111111111111111111111111111111111111111111111111111111111111111111" "22222222222222222222222222222222222222222222222222222222222222222222222222222222" "33333333333333333333333333333333333333333333333333333333333333333333333333333333" "44444444444444444444444444444444444444444444444444444444444444444444444444444444" "55555555555555555555555555555555555555555555555555555555555555555555555555555555" "66666666666666666666666666666666666666666666666666666666666666666666666666666666" "77777777777777777777777777777777777777777777777777777777777777777777777777777777" "88888888888888888888888888888888888888888888888888888888888888888888888888888888" "99999999999999999999999999999999999999999999999999999999999999999999999999999999" "00000000000000000000000000000000000000000000000000000000000000000000000000000000"; memcpy(buf+(4*80), buf+(3*80), 7*80); memcpy(buf+(3*80), temp, 80); printf("%s\n", buf); return 0; }
 
이미 이제 예상했지만 다음과 같은 결과를 얻었습니다. (참담하게도...)
 
11111111111111111111111111111111111111111111111111111111111111111111111111111111 22222222222222222222222222222222222222222222222222222222222222222222222222222222 33333333333333333333333333333333333333333333333333333333333333333333333333333333 ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ 44444444444444444444444444444444444444444444444444444444444444444444444444444444 44444444444444444444444444444444444444444444444444444444444444444444444444444444 44444444444444444444444444444444444444444444444444444444444444444444444444444444 44444444444444444444444444444444444444444444444444444444444444444444444444444444 44444444444444444444444444444444444444444444444444444444444444444444444444444444 44444444444444444444444444444444444444444444444444444444444444444444444444444444 44444444444444444444444444444444444444444444444444444444444444444444444444444444
 
이제 다음과 같이 첫번째 memcpy()를 memmove()로 변경하여서 해 보았습니다.
 
#include <stdio.h> #include <memory.h> int main(int argc, char *argv[]) { char temp[102]="ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ"; char buf[1020]= "11111111111111111111111111111111111111111111111111111111111111111111111111111111" "22222222222222222222222222222222222222222222222222222222222222222222222222222222" "33333333333333333333333333333333333333333333333333333333333333333333333333333333" "44444444444444444444444444444444444444444444444444444444444444444444444444444444" "55555555555555555555555555555555555555555555555555555555555555555555555555555555" "66666666666666666666666666666666666666666666666666666666666666666666666666666666" "77777777777777777777777777777777777777777777777777777777777777777777777777777777" "88888888888888888888888888888888888888888888888888888888888888888888888888888888" "99999999999999999999999999999999999999999999999999999999999999999999999999999999" "00000000000000000000000000000000000000000000000000000000000000000000000000000000"; memmove(buf+(4*80), buf+(3*80), 7*80); memcpy(buf+(3*80), temp, 80); printf("%s\n", buf); return 0; }
 
결과는 다음과 같았습니다.
 
11111111111111111111111111111111111111111111111111111111111111111111111111111111 22222222222222222222222222222222222222222222222222222222222222222222222222222222 33333333333333333333333333333333333333333333333333333333333333333333333333333333 ABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJABCDEFGHIJ 44444444444444444444444444444444444444444444444444444444444444444444444444444444 55555555555555555555555555555555555555555555555555555555555555555555555555555555 66666666666666666666666666666666666666666666666666666666666666666666666666666666 77777777777777777777777777777777777777777777777777777777777777777777777777777777 88888888888888888888888888888888888888888888888888888888888888888888888888888888 99999999999999999999999999999999999999999999999999999999999999999999999999999999 00000000000000000000000000000000000000000000000000000000000000000000000000000000
 
어찌되었건 지금은 해결이 되었지만...
어째 쫌 억울한 생각이 드는건 왜일까요? ㅠㅠ
 
나만 몰랐던 거야? 그런거야~ 
 
참. 참고로 memmove()는 메모리 이동시 temp영역에 메모리를 복사하여 오버랩된 메모리를 보호합니다. 고로 memmove()는 memcpy()에 비해 부하가 조금이나마 더 있습니다.
그래서 memmove()는 필요할 때만 사용하세요.
 
Creative Commons License
Creative Commons License이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Copyright 조희창(Nicholas Jo). Some rights reserved. http://bbs.nicklib.com