program tip

C에서 0에 대한 포인터 역 참조

radiobox 2021. 1. 8. 08:04
반응형

C에서 0에 대한 포인터 역 참조


때때로 메모리 주소 0x0의 데이터는 매우 가치가 있습니다. x86 리얼 모드 IVT를 더 잘 알려진 예로 생각해보십시오 : 0x0에서 시작하고 인터럽트 핸들러에 대한 포인터를 포함합니다. 0x00에있는 dword는 0으로 나누는 오류 핸들러에 대한 포인터입니다.

그러나 C11 언어 표준 은 0으로 초기화 된 포인터 또는 널 포인터로 초기화 된 포인터 [WG14 N1570 6.3.2.3] 로 정의 된 널 포인터 [WG14 N1570 6.5.3.2]의 역 참조를 금지하여 첫 번째 바이트를 효과적으로 금지합니다.

사람들은 필요할 때 실제로 0x0을 어떻게 사용합니까?


C는 널 포인터의 역 참조를 금지 하지 않고 정의되지 않은 동작을 만듭니다.

주소를 포함하는 포인터를 역 참조 할 수있는 환경이라면 0x0그렇게 할 수 있어야합니다. C 언어 표준은 그렇게 할 때 일어날 일에 대해 아무것도 말하지 않습니다. (대부분의 환경에서 결과는 프로그램 충돌입니다.)

구체적인 예 (정확히 기억하고 있다면) : 68k 기반 Sun 3 컴퓨터에서 널 포인터를 역 참조해도 트랩이 발생하지 않았습니다. 대신 OS는 메모리 주소 0에 0 값을 저장했고, null 포인터 (주소 0을 가리킴)를 역 참조하면 해당 0 값이 생성됩니다. 예를 들어, C 프로그램은 널 포인터를 마치 빈 문자열에 대한 유효한 포인터처럼 취급 할 수 있습니다. 일부 소프트웨어는 의도적이든 아니든이 동작에 의존했습니다. 이를 위해서는 널 포인터 역 참조에 갇힌 SPARC 기반 Sun 4로 소프트웨어를 포팅 할 때 많은 정리가 필요했습니다. (나는 이것에 대해 읽은 것을 분명히 기억하지만 참조를 찾을 수 없었습니다. 찾을 수 있으면 업데이트하겠습니다.)

널 포인터가 주소가 0 일 필요 없습니다 . 보다 정확하게는 null의 표현이 모두 0 비트 일 수도 있고 아닐 수도 있습니다. 매우 일반적이지만 보장되지는 않습니다. (그렇지 않은 경우 정수에서 포인터로의 변환은 (void*)0중요하지 않습니다.)

comp.lang.c FAQ 의 섹션 5 에서는 널 포인터에 대해 설명합니다.


사람들은 필요할 때 실제로 0x0을 어떻게 사용합니까?

중 하나에 의해:

  • 어셈블리 언어로 필요한 코드 작성 또는
  • C로 코드를 작성하고 컴파일러가 원하는 작업에 대해 올바른 어셈블리 언어를 생성하는지 확인

진술 :

char * x = 0;

반드시 0x0을 x에 넣지는 않습니다. 현재 아키텍처 및 컴파일러에 대해 정의 된 널 포인터 값을 x에 넣습니다.

이제 실질적인 측면에서 일반적으로 사용되는 모든 컴파일러 / 프로세서는 해당 명령문에 대한 응답으로 레지스터 또는 저장 위치의 행에 32 (또는 64) 0 비트를 넣습니다. 따라서 메모리 주소 0이 유용하다면, 그런 다음 다른 사람들이 지적했듯이 공식적으로 정의되지 않은 동작을 사용하고 있습니다. 그러나 옛날 옛적에 '널 포인터'가 모두 0 아닌 비트 패턴 인 하드웨어가 있었고 , 누가 알겠는가?


Annex J 다음과 같은 경우 정의되지 않은 동작입니다.

단항 * 연산자의 피연산자에 유효하지 않은 값 (6.5.3.2)이 있습니다.

언급 한 동일한 각주에서 널 포인터는 유효하지 않은 값이라고 말합니다. 따라서 금지 된 것이 아니라 정의되지 않은 동작입니다. 주소 0x0와 널 포인터 의 구별 에 대해서는 메모리 주소 0x0을 사용할 수 있습니까?를 참조하십시오 . .

널 포인터가 반드시 주소 0x0 일 필요는 없으므로 아키텍처는 잠재적으로 다른 주소를 선택하여 널 포인터를 나타낼 수 있으며 new에서 유효한 주소로 0x0을 얻을 수 있습니다.

null 포인터가 Operative System에 의해 예약되었는지 또는 C ++ 구현에 의해 예약되었는지 여부는 지정되지 않았지만, plain new는 주소가 무엇이든간에 null 포인터를 반환하지 않습니다 (new new는 다른 짐승이 아닙니다). 따라서 귀하의 질문에 답하려면 :

메모리 주소 0x0을 사용할 수 있습니까?

아마도 특정 구현 / 아키텍처에 따라 다릅니다.

즉, 0x0시스템에서 충돌을 일으키지 않는다고 확신한다면 자유롭게 사용 하십시오.


운영 체제는 포인터 테이블을 사용하여 루틴을 인터럽트하여 적절한 인터럽트를 호출합니다. 일반적으로 (대부분의 운영 체제에서) 포인터 테이블은 낮은 메모리 ( 처음 수백 개 정도의 위치)에 저장됩니다. 이러한 위치는 다양한 장치에 대한 인터럽트 서비스 루틴의 주소를 보유합니다.

그래서 당신이 할 때

char *ptr = 0x0; 

그런 다음 인터럽트 서비스 루틴의 주소로 포인터를 초기화 할 가능성이 높습니다. 운영 체제에 속한 메모리 위치를 역 참조 (또는 수정)하면 프로그램이 충돌 할 가능성이 높습니다.
따라서 0x0OS에 속하지 않는다는 확인을받을 때까지 포인터를 초기화 하고 역 참조하지 않는 것이 좋습니다.

참조 URL : https://stackoverflow.com/questions/21104702/dereferencing-a-pointer-to-0-in-c

반응형