프로그래밍시스템 프로그래머

C에서 표준 memcpy 함수는 어떻게 작동하며, 어떤 용도로 사용되며, 다양한 유형의 메모리를 복사할 때 어떤 문제점이 발생할 수 있나요?

Hintsage AI 어시스턴트로 면접 통과

답변.

표준 라이브러리(string.h)의 memcpy 함수는 메모리 영역을 한 바이트씩 복사하는 데 사용됩니다. 이것은 배열, 구조체 및 기타 데이터 블록을 복사할 때 성능이 중요하고 형 변환이 필요하지 않은 범용 도구입니다.

문제의 역사:
memcpy는 첫 번째 표준 라이브러리 구현과 함께 등장했으며, "원시" 메모리 블록을 처리할 필요성이 있었기 때문에 생겨났습니다. 예를 들어 파일 작업, 네트워크 패킷 및 데이터 직렬화를 위한 것입니다. 유사한 함수는 거의 모든 저수준 언어에 존재합니다.

문제:
memcpy는 바이트로만 작동하며 데이터 유형, 정렬 또는 메모리 영역의 겹침에 대해 신경 쓰지 않습니다. 크기 또는 잘못된 영역 지정을 오류가 발생하면 메모리 손상 또는 예기치 않은 결과가 발생할 수 있습니다. 또한, 겹치는 영역에 대해 memcpy를 사용할 경우 정의되지 않은 동작이 발생합니다.

해결책:
아래와 같은 경우에만 memcpy를 사용하십시오:

  • 영역이 겹치지 않을 경우;
  • 복사된 데이터가 대상 유형에 대해 올바르게 해석될 수 있는 경우;
  • 복사하는 블록의 크기가 올바르게 지정된 경우.
    겹치는 영역에 대해서는 memmove 함수를 사용하십시오.

코드 예:

#include <string.h> typedef struct { int id; float value; } Item; Item src = {42, 3.14f}; Item dest; memcpy(&dest, &src, sizeof(Item)); // 구조체를 바이트 단위로 복사합니다.

주요 특징:

  • 형 변환을 수행하지 않습니다.
  • 배열의 경계를 초과하는 것을 검증하지 않습니다.
  • 원본 및 대상 블록의 겹침 시 정의되지 않은 동작을 일으킬 수 있습니다.

함정이 있는 질문.

strlen을 복사하기 위해 memcpy를 사용할 수 있나요?

가능하지만 길이를 정확히 아는 경우에만 가능합니다. 만약 문자열이 null-terminated이면, strcpy 또는 strncpy를 사용하는 것이 일반적입니다. 크기를 혼동하면 메모리 초과 또는 null 종료문자가 손실될 수 있습니다.

char src[] = "abc"; char dest[4]; memcpy(dest, src, 4); // 3 문자 + '\0'이 복사됩니다.

비표준 정렬이나 포인터를 가진 구조체를 memcpy로 복사하면 어떻게 되나요?

memcpy는 의미론이나 내부 포인터를 고려하지 않습니다. 구조체가 동적 필드(char *buf;와 같은)를 저장하는 경우, 주소만 복사되고 해당 주소의 내용은 복사되지 않습니다. 이는 이른바 "표면 복사"를 초래합니다.

typedef struct { char *buf; } Wrapper; Wrapper src = {malloc(10)}; Wrapper dest; memcpy(&dest, &src, sizeof(Wrapper)); // 포인터 필드만 복사되고 내용은 복사되지 않습니다.

memcpy에서 src와 dest가 겹치는 경우에는 어떻게 되나요?

표준에 의해 정의되지 않은 동작이 발생할 수 있으며 데이터 손실이 발생할 수 있습니다. 겹치는 복사를 하려면 memmove를 사용하십시오:

memmove(dest, src, size); // 정확한 복사를 보장합니다.

일반적인 실수와 안티 패턴

  • src와 dest가 겹치는 복사
  • 바이트 수 계산 오류 (형의 sizeof가 아닌 포인터의 sizeof)
  • 동적이거나 숨겨진 자원을 가진 구조체 복사 ("얕은 복사" 대신 깊은 복사 사용)

현실에서의 예

부정적인 사례

배열이 겹칠 때: memcpy를 사용하여 배열의 일부를 오른쪽으로 이동하는 경우, src와 dest가 부분적으로 겹칩니다.

장점:

  • 대부분의 플랫폼에서 빠르게 작동합니다.

단점:

  • 데이터 손실, 정의되지 않은 동작, 예측할 수 없는 버그 발생 가능성

긍정적인 사례

겹치는 영역 처리를 위해 memmove를 사용하는 경우로, 데이터 양이 원본 구조체의 바이트 수로 정확하게 계산됩니다.

장점:

  • 안전한 복사
  • 가독성이 좋고 유지보수가 용이

단점:

  • memcpy에 비해 성능이 약간 낮습니다.