bestsource

memcpy 0바이트를 상수 변수로 - 정의되지 않은 동작?

bestsource 2023. 9. 11. 21:55
반응형

memcpy 0바이트를 상수 변수로 - 정의되지 않은 동작?

C 및 C++에서 다음과 같이 정의되지 않은 동작이 있습니까?memcpyconst복사할 바이트 수가 0일 때 변수?

int x = 0;
const int foo = 0;
memcpy( (void *)&foo, &x, 0 );

이 질문은 순수하게 이론적인 것은 아닙니다.제가 시나리오를 가지고 있는데요.memcpy를 호출하고 대상 포인터가 다음을 가리킬 경우constmemory, size 인수는 0으로 보장됩니다.그래서 특별한 경우로 처리해야 하는지 궁금합니다.

이전 질문인 Memcpy(0,0,0)를 수행하는 것이 안전한지는 7.1.4p1을 지적합니다.

다음의 각 문은 다음의 상세한 설명에 달리 명시적으로 언급되지 않는 한 적용됩니다.함수에 대한 인수가 잘못된 값(예: 함수의 도메인 밖의 값, 프로그램의 주소 공간 밖의 포인터, null 포인터, 해당 매개 변수가 상수 자격이 없는 경우 수정할 수 없는 저장소에 대한 포인터)을 갖거나 변수 번호를 가진 함수가 예상하지 않는 유형(촉진 후)을 가진 경우인수의 동작은 정의되지 않습니다.

의 원형.memcpy

void *memcpy(void * restrict s1, const void * restrict s2, size_t n);

여기서 첫번째 파라미터는const-자격이 있고,&foo수정할 수 없는 저장소를 가리킵니다.그래서 이 코드는 설명이 없는 한 UB입니다.memcpy는 명시적으로 달리 명시하고 있지만 그렇지 않습니다.단지 다음과 같은 말뿐입니다.

memcpy 함수는 s2가 가리키는 객체에서 s1이 가리키는 객체로 n개의 문자를 복사합니다.

이것은 다음을 암시합니다.memcpy…을 헤아려 보면0는 어떤 문자도 복사하지 않습니다. (또한 7.24.1p2 "0 문자를 복사합니다. Lundin 감사합니다.) 그러나 유효한 인수를 통과하기 위한 요구 사항을 면제하지는 않습니다.

대부분의 플랫폼에서 소스 및 대상 포인터의 유효성에 관계없이 memcpy(무엇이든, 무엇이든, 0)를 노옵(No-op)으로 처리하는 구현은 모든 면에서, 본질적으로 모든 비제한적 시나리오에서, 다른 어떤 것을 수행하는 구현보다 좋거나 더 나은 구현임이 분명합니다.

그러나 표준이 작성되는 방식은 컴파일러가 대상 주소가 쓰기 가능 저장소와 연결되지 않은 모든 상황을 UB로 처리할 수 있도록 지정하는 것으로 해석될 수 있습니다.

만약 표준이 그러한 행동을 명확하게 요구하는지의 여부를 고려하지 않고, 표준의 저자들에 의해 출판된 근거 문서에 문서화된 철학을 적용하여 구석 사례를 처리하고자 하는 구현을 사용하는 경우, 모든 것memcpy그리고.memmove크기가 0인 작업은 안정적으로 노옵스로 처리됩니다.크기가 종종 0인 경우, a를 건너뛰는 것에 대한 성능상의 이점이 있을 수 있습니다.memcpy아니면memmove제로 사이즈의 케이스를 호출하지만, 정확성을 위해서는 그러한 체크가 필요하지 않습니다.

그러나 코드가 100% 명확하게 표준에 의해 의무화되지 않은 코너 케이스를 트리거하는 입력을 결코 수신하지 않을 것이라고 적극적으로 가정하고 그러한 입력이 수신될 경우 무의미한 코드를 생성하도록 설계된 컴파일러 구성과 신뢰성 있는 호환성을 보장하고자 한다면 크기==0ch를 추가해야 합니다.쓰기 가능한 저장소에 대한 포인터 이외의 다른 항목이 0 크기에 포함될 수 있는 경우에는 이러한 검사가 크기가 0인 경우가 거의 없는 상황에서 성능에 부정적인 영향을 미칠 수 있음을 확인합니다.

언급URL : https://stackoverflow.com/questions/74005650/memcpy-zero-bytes-into-const-variable-undefined-behavior

반응형