C의 0에 대한 포인터 참조 해제
메모리 주소 0x0 의 데이터는 매우 중요한 경우가 있습니다.x86 real mode IVT 를 예로 들 수 있습니다.이는 0x0 에서 시작하여 핸들러를 인터럽트하는 포인터를 포함합니다.0x00 의 dword 는 에러 핸들러 0 으로 나눗셈하는 포인터입니다.
단, C11 언어 표준에서는 0으로 초기화된 포인터 또는 Null 포인터로 초기화된 포인터 [WG14 N1570 6.3.2]로 정의되어 사실상 첫 번째 바이트를 금지하고 있습니다.
실제로 0x0은 필요할 때 어떻게 사용합니까?
C는 늘 포인터의 참조를 금지하지 않습니다.정의되지 않은 동작을 할 뿐입니다.
사용자 환경이 주소를 포함하는 포인터를 참조 해제할 수 있는 경우0x0
그럼 그렇게 할 수 있을 거예요.C 언어 표준에서는 이 경우 어떤 일이 일어나는지에 대해 언급하지 않습니다(대부분의 환경에서는 프로그램 크래시가 발생합니다).
구체적인 예(내 기억이 맞는 경우):68k 기반의 Sun 3 컴퓨터에서는 늘 포인터를 참조해도 트랩이 발생하지 않습니다.대신 OS는 메모리 주소 0에 제로 값을 저장했고 늘 포인터(주소 0을 가리키고 있음)를 참조하면 제로 값이 생성됩니다.이는 예를 들어 C 프로그램이 빈 문자열에 대한 유효한 포인터인 것처럼 처리할 수 있음을 의미합니다.의도적이든 의도적이든 아니든 일부 소프트웨어는 이 동작에 의존했습니다.이를 위해서는 소프트웨어를 SPARC 기반의 Sun 4로 이식할 때 많은 양의 청소가 필요했습니다.Sun 4는 늘 포인터 레퍼리에 갇혀 있었습니다.(이것을 읽은 것은 분명히 기억하고 있습니다만, 레퍼런스를 찾을 수 없었습니다.찾을 수 있으면 갱신하겠습니다.)
늘 포인터는 반드시 주소0은 아닙니다.보다 정확하게는 null의 표현은 all-bits-zero일 수도 있고 아닐 수도 있습니다.아주 흔하지만 장담할 수는 없어요.(그렇지 않은 경우 정수에서 포인터로 변환합니다).(void*)0
는 비표준입니다).
comp.lang.c FAQ 섹션5에서는 늘 포인터에 대해 설명합니다.
실제로 0x0은 필요할 때 어떻게 사용합니까?
다음 중 하나에 의해:
- 어셈블리 언어로 필요한 코드를 작성하거나
- C로 코드를 작성하고 컴파일러가 원하는 작업에 대해 올바른 어셈블리 언어를 생성하는지 확인합니다.
스테이트먼트:
char * x = 0;
는 반드시 0x0을 x에 넣을 필요는 없습니다.현재 아키텍처 및 컴파일러에 대해 정의된 늘 포인터 값을 x에 넣습니다.
실제로 사용되는 컴파일러/프로세서는 모두 이 스테이트먼트에 대응하여 32(또는 64)0비트를 레지스터 또는 스토리지 로케이션의 행에 넣습니다.따라서 메모리주소 0이 유용하다면 다른 사람이 지적한 바와 같이 정식으로 정의되지 않은 동작을 사용할 수 없게 됩니다.그러나 옛날 옛적에는 '늘 포인터'가 모두 0이 아닌 비트 패턴인 하드웨어가 있었습니다.또 다시 존재할 수도 있습니다.
부록 J 정의되지 않은 동작은 다음과 같다.
단항 * 연산자의 피연산자에 잘못된 값(6.5.3.2)이 있습니다.
말씀하신 각주에는 늘 포인터가 유효하지 않은 값이라고 표시되어 있습니다.따라서 이는 금지되는 것이 아니라 정의되지 않은 동작입니다.주소의 구별에 대해서0x0
및 null 포인터는 메모리 주소 0x0을 사용할 수 있습니까?를 참조하십시오.
null 포인터는 반드시 주소 0x0은 아니기 때문에 아키텍처에서 null 포인터를 나타내는 다른 주소를 선택하고 new에서 유효한 주소로 0x0을 얻을 수 있습니다.
늘 포인터가 운영시스템에 의해 예약되어 있는지, C++ 실장이 지정되어 있지 않은지에 관계없이 플레인 new는 그 주소가 무엇이든 늘 포인터를 반환하지 않습니다(nothrow new는 다른 beast).질문에 대한 답변은 다음과 같이 하십시오.
메모리 주소 0x0을 사용할 수 있습니까?
특정 구현/아키텍처에 따라 다를 수 있습니다.
즉, 자유롭게 사용하실 수 있습니다.0x0
크래시를 일으키지 않을 것이 확실하다면 말이죠.
운영체제는 포인터 테이블을 사용하여 루틴을 인터럽트하고 적절한 인터럽트를 호출합니다.일반적으로 (대부분의 운영체제에서) 포인터 테이블은 낮은 메모리(처음 수백 개 정도의 위치)에 저장됩니다.이러한 위치에는 다양한 디바이스의 인터럽트 서비스 루틴의 주소가 저장됩니다.
그래서 당신이 할 때
char *ptr = 0x0;
인터럽트 서비스 루틴의 주소로 포인터를 초기화하고 있을 가능성이 높습니다.operating system에 속하는 메모리 위치를 참조(또는 변경)하면, 프로그램이 크래쉬 할 가능성이 있습니다.
따라서 포인터를 초기화하지 않는 것이 좋습니다.0x0
OS가 아닌 것을 확인할 때까지 참조를 해제합니다.
언급URL : https://stackoverflow.com/questions/21104702/dereferencing-a-pointer-to-0-in-c
'programing' 카테고리의 다른 글
Jackson에서 JSON 문자열을 JsonNode로 해석하려면 어떻게 해야 합니까? (0) | 2022.08.16 |
---|---|
구조물을 기능으로 전달 (0) | 2022.08.15 |
캐시가 VUE JS 애플리케이션에서 이전 업데이트된 사진을 표시함 (0) | 2022.08.15 |
정규화된 데이터가 있는 Vuex getter가 반응하지 않음 (0) | 2022.08.15 |
상태가 200이고 응답이 있어도 Axios POST는 "Network Error"를 반환한다. (0) | 2022.08.15 |