programing

Can C++ array end at memory boundary?

megabox 2023. 11. 5. 11:07
반응형

Can C++ array end at memory boundary?

C++ standard (and C for that matter) allows to create (not dereference though) a pointer to one element past the end of the array. Does this mean that an array will never be allocated at such a location that its last element ends at the memory boundary? I understand that in practice some/all implementation might follow this convention, but which one the following is true:

  1. It's actually false, and an array might end at memory boundary, OR
  2. It is mandated by C++ standard to end at least one element's worth of memory before the boundary, OR
  3. Neither 1, nor 2, but it is still like that in actual compilers because it makes implementation easier.

Is anything different for the case of C?

업데이트 : 1이 정답인 것 같습니다.아래 James Kanze의 답변을 참조하십시오.efence(http://linux.die.net/man/3/efence - 그것에 대한 포인터를 준 Michael Chastain에게 감사드립니다.)

An implementation must allow a pointer to one past the end to exist. How it does this is its business. On many machines, you can safely put any value into a pointer, without risk (unless you dereference it); on such systems, the one past the end pointer may point to unmapped memory—I've actually encountered a case under Windows where it did.

On other machines, just loading a pointer to unmapped memory into a register will trap, causing the program to crash. On such machines, the implementation must ensure that this doesn't happen, either by refusing to use the last byte or word of allocated memory, or by ensuring that all use of the pointer other than dereferencing it avoids any instructions which might cause the hardware to treat it as an invalid pointer. (Most such systems have separate address and data registers, and will only trap if the pointer is loaded into an address register. If the data registers are large enough, the compiler can safely load the pointer into a data register for e.g. comparison. This is often necessary anyway, as the address registers don't always support comparison.)

마지막 질문을 다시 하십시오. 이 점에서 C와 C++는 정확히 일치합니다. C++는 단순히 C로부터 규칙을 넘겨받았을 뿐입니다.

§3.9.2/3[복합형]에 흥미로운 통로가 있습니다.

void로 표시할 포인터의 유형 또는 개체 유형의 포인터를 개체 포인터 유형이라고 합니다. [...] 개체 포인터 유형의 유효한 값은 메모리의 바이트 주소(1.7) 또는 null 포인터(4.10)를 나타냅니다.

§5.7/5 [추가 연산자]의 텍스트와 함께:

[...] 또한, 식 P가 어레이 객체의 마지막 요소를 가리키면, 식 (P)+1이 어레이 객체의 마지막 요소를 하나 가리키고, 식 (Q)-1이 어레이 객체의 마지막 요소를 하나 가리키면, 식 (Q)-1이 어레이 객체의 마지막 요소를 가리킵니다.

메모리의 마지막 바이트로 끝나는 배열은 할당할 수 없는 것 같습니다. 한 번의 끝 포인터가 유효해야 한다는 요구 사항이 있는 경우입니다.만약 한 번의 끝을 가리키는 포인터가 유효하지 않다면, 저는 답을 모릅니다.

§3.7.4.2/4절 [할당 해제 기능]은 다음과 같이 기술합니다.

잘못된 포인터 값을 사용하는 경우(할당 해제 함수에 전달하는 경우 포함)의 효과는 정의되지 않습니다.

따라서 할당된 배열에 대해 한 번의 끝 포인터를 비교하는 것이 지원되어야 하는 경우에는 한 번의 끝 포인터가 유효해야 합니다.

제가 받은 의견을 토대로 볼 때, 저는 구현이 어레이의 한 끝 포인터가 사용 가능한지 여부에 신경 쓰지 않고 어레이를 할당할 수 있다고 생각합니다.다만 이에 대한 기준에서 관련된 부분을 알아보고 싶습니다.

반은 옳아요.가상 구현에서 선형 주소 지정 메모리와 16비트 부호 없는 정수로 표시되는 포인터를 사용한다고 가정합니다.또한 null 포인터가 0으로 표시된다고 가정합니다.그리고 마지막으로, 당신이 16바이트의 메모리를 요구한다고 가정하고,char *p = malloc(16);. 그러면 숫자 값이 65520보다 작은 포인터를 얻을 수 있습니다.65520이라는 값 자체는 유효하지 않을 것입니다. 왜냐하면 여러분이 정확히 지적하신 것처럼, 할당이 성공했다고 가정하면,p + 16는 Null 포인터가 되어서는 안 되는 유효한 포인터입니다.

그러나 이제 가상 구현에서 선형 주소 지정 메모리와 32비트 부호 없는 정수로 표현되는 포인터를 사용하지만 주소 공간은 16비트에 불과하다고 가정합니다.또한 null 포인터가 0으로 표시된다고 가정합니다.그리고 마지막으로, 당신이 16바이트의 메모리를 요구한다고 다시 한번 가정해 보겠습니다.char *p = malloc(16);. 그러면 숫자 값이 65520보다 작거나 같은 포인터만 얻을 수 있습니다.65520이라는 값 자체가 유효할 것입니다. 구현을 통해 16을 더하면 65536이라는 값이 나오고 16을 빼면 65520으로 돌아갑니다.주소 65536에 메모리(물리적 또는 가상)가 전혀 없는 경우에도 유효합니다.

표준은 포인터를 마지막 요소로 증가시킬 때 발생하는 동작을 명시적으로 명시합니다.배열이 종료되기 전인지 또는 종료되기 전인지 확인하기 위한 비교로만 사용할 수 있는 값을 제공합니다.포인터는 다른 개체에 대해 유효하게 할당된 메모리를 가리킬 수 있지만, 이는 완전한 정의되지 않은(구현 정의된?) 동작이며 이 포인터를 사용하는 것은 확실히 정의되지 않은 동작입니다.

제가 얻고자 하는 것은, 한 번의 끝을 가리키는 포인터가 바로 그것입니다. 마지막 요소로 포인터를 늘리면 아주 저렴한 방법으로 배열의 끝을 표시할 수 있는 포인터입니다.그러나 관련이 없는 객체의 포인터를 비교하는 것은 완전히 말도 안 되는 일입니다. (만약 제가 착각하지 않았다면, 심지어 정의되지 않은 행동도 있을 수 있습니다.)따라서 포인터 "값"이 서로 다른 개체 간에 중복될 수 있다는 사실은 문제가 되지 않습니다. 이를 이용하면 정의되지 않은 동작의 땅으로 들어갈 수 있기 때문입니다.

이는 구현에 따라 달라집니다.적어도 시각적인 C++에서는 배열 경계 검사를 사용하지 않고 배열의 끝을 지나는 요소의 수에 상관없이 포인터를 만들 수 있습니다.참조를 취소해도 액세스 중인 메모리 주소가 프로그램의 할당된 힙/스택 내에 있는 한 여전히 작동합니다.해당 메모리 위치의 값이 무엇이든 읽거나 수정하게 됩니다.주소가 할당된 메모리 공간 밖에 있으면 오류가 발생합니다.

이런 종류의 코딩은 추적하기 매우 어려운 버그를 만들기 때문에 디버거는 이러한 것들을 탐지하기 위한 검사를 수행합니다.

언급URL : https://stackoverflow.com/questions/26420348/can-c-array-end-at-memory-boundary

반응형