특수한 포인터

Null pointer

컴퓨팅에서 포인터 또는 늘 참조는 포인터 또는 참조가 유효한 객체를 참조하지 않음을 나타내기 위해 저장된 값입니다.프로그램에서 늘 포인터를 사용하여 알 수 없는 길이의 목록 끝이나 일부 작업 수행 실패와 같은 조건을 나타냅니다. 이러한 늘 포인터의 사용은 늘 가능 유형 및 옵션 유형의 아무것도 아닌 값과 비교할 수 있습니다.

null 포인터는 초기화되지 않은 포인터와 혼동해서는 안 됩니다.null 포인터는 유효한 객체를 가리키는 포인터와 동등하지 않음을 보증합니다.다만, 언어나 실장에 따라서는, 초기화되지 않은 포인터에는 그러한 보증이 없는 경우가 있습니다.다른 유효한 포인터와 동등하게 비교하거나 늘 포인터와 동등하게 비교할 수 있습니다.둘 다 다른 시간에 수행되거나 비교가 정의되지 않은 동작일 수 있습니다.

C

C에서는 임의의 유형의 두 개의 늘포인터가 동등하게 [1]비교됩니다.프리프로세서 매크로NULL구현 정의 늘 포인터 [2]상수로 정의됩니다.C99 에서는, 다음과 같이 포터블하게 나타낼 수 있습니다.((void *)0)즉, 정수값이0형으로 변환되다void*([3]무효가 됩니다).C 표준에서는 늘 포인터가 메모리주소 0에 대한 포인터와 동일하다고는 하지 않습니다.다만, 실제로는 그렇게 되어 있을 가능성이 있습니다. 포인터의 디레퍼런스는 [4]C에서 정의되지 않은 동작이며, 준거 실장에서는 참조된 포인터가 늘이 아니라고 가정할 수 있습니다.

실제로 늘 포인터를 참조하면 매핑되지 않은 메모리에서 읽기 또는 쓰기가 시도되어 분할 장애 또는 메모리 액세스 위반이 트리거될 수 있습니다.이는 프로그램 크래시로 나타나거나 프로그램 코드로 탐지할 수 있는 소프트웨어 예외로 변환될 수 있습니다.그러나 그렇지 않은 특정 상황이 있습니다.예를 들어 x86real 모드에서 주소는0000:0000는 가독성이 있어 보통 기입도 가능합니다.또, 그 주소로 포인터를 되돌리는 것은 지극히 유효하지만, 통상은 바람직하지 않은 액션으로, 애플리케이션내에서 정의되어 있지 않지만, 부정하게 동작할 가능성이 있습니다.주소 0에 대한 포인터의 역참조가 의도적이고 명확하게 정의되어 있는 경우가 있습니다.예를 들어 16비트 리얼 모드 x86 디바이스의 경우 BIOS 코드는 쓰기용 늘 포인터를 역참조함으로써 머신의 물리 주소 0에 IDT를 쓸 수 있습니다.또한 컴파일러는 늘 포인터 참조를 최적화하여 분할 오류를 방지하고 다른 바람직하지 않은 동작을 발생시킬 수 있습니다.

C++

C++에서는,NULL매크로가 C에서 상속되었으며, 0의 정수 리터럴은 전통적으로 늘 포인터 [5]상수를 나타내기 위해 선호되어 왔습니다.단, C++11은 명시적인 늘 포인터 상수를 도입했습니다.nullptr대신 사용할 수 있습니다.

기타 언어

일부 프로그래밍 언어 환경(예를 [citation needed]들어 적어도1개의 독자적인 Lisp 실장)에서는 늘 포인터로서 사용되는 값(라 불린다).nil(Lisp에서)는 실제로 구현에 유용한 내부 데이터 블록에 대한 포인터일 수 있습니다(그러나 사용자 프로그램에서는 명시적으로 도달할 수 없습니다). 따라서 동일한 레지스터를 구현 내부 액세스에 유용한 상수로서 빠르게 사용할 수 있습니다.이것은 벡터라고 알려져 있다.

태그가 달린 아키텍처를 가진 언어에서 null 포인터는 예외적인 경우를 명시적으로 처리하는 태그가 달린 결합으로 대체될 수 있습니다.실제로 null 포인터는 계산된 태그가 달린 태그가 달린 포인터로 볼 수 있습니다.

프로그래밍 언어에서는 늘 포인터에 다른 리터럴을 사용합니다.예를 들어 Python에서는 null 값이 호출됩니다.NonePascalSwift에서는 늘 포인터가 호출됩니다.nil에펠에서, 그것은 a라고 불린다.void언급.

무효참조

늘 포인터는 의미 있는 오브젝트를 가리키지 않기 때문에 늘 포인터를 참조 해제(즉, 메모리 위치에 저장된 데이터에 액세스)하려고 하면 런타임 오류 또는 즉각적인 프로그램 크래시가 발생합니다.

  • C에서 늘 포인터의 역참조는 정의되지 않은 [4]동작입니다.null 포인터 표현은 오브젝트를 저장하기 위해 시스템에 의해 할당되지 않은 주소로 선택되기 때문에 많은 구현에서는 이러한 코드가 액세스 위반으로 인해 프로그램이 중지됩니다.그러나 이 동작은 보편적이지 않습니다.컴파일러는 정의되지 않은 동작이 없다는 가정 하에 프로그램을 최적화할 수 있기 때문에 이 또한 보장되지 않습니다.
  • 델파이와 다른 많은 파스칼 구현에서 상수는nil는 메모리 내의 첫 번째 주소에 대한 늘포인터를 나타냅니다.이 포인터는 관리대상 변수의 초기화에도 사용됩니다.역참조 시 외부 OS 예외가 발생합니다.이 예외는 시스템의 경우 Pascal EAccessViolation 예외 인스턴스에 매핑됩니다.SysUtils 유닛은 uses 구에 링크되어 있습니다.
  • Java에서는 null 참조에 액세스하면NullPointerException에러 처리 코드에 의해서 검출될 가능성이 있습니다만, 이러한 예외가 발생하지 않게 하는 것이 바람직합니다.
  • 리스프에서는 nero는 퍼스트클래스 객체입니다.그렇게(first nil)nero 입니다.(rest nil)0 입니다.따라서 참조가 0이 되어도 에러는 발생하지 않지만, 올바르게 기술되지 않은 코드는 무한 루프 상태가 될 수 있습니다.
  • .NET에서는 늘 참조에 액세스하면 NullReferenceException이 트리거됩니다.이러한 예외 유형을 탐지하는 것은 일반적으로 잘못된 관행으로 간주되지만 이 예외 유형은 프로그램에 의해 탐지되고 처리될 수 있습니다.
  • Objective-C 에서는, 메세지가 송신되는 일이 있습니다.nil오브젝트(Null 포인터)는 프로그램을 중단시키지 않습니다.메시지는 단순히 무시되며 반환값(있는 경우)은nil또는0([6]유형에 따라 다릅니다).
  • SMAP가 도입되기 전에는 페이지0을 공격자의 주소 공간에 매핑하여 Null 포인터가 해당 영역을 가리키도록 함으로써 Null 포인터 참조 해제 버그를 이용할 수 있습니다.이로 인해 경우[7]따라 코드가 실행될 수 있습니다.

경감

늘 포인터 [8][9]디버깅을 용이하게 하는 기술이 있습니다.본드 [8]등은 늘 전파를 추적하기 위해 JVM을 수정할 것을 제안한다.Casper[9] 시스템의 개념은 JVM을 변경하지 않고 소스 코드 변환을 사용하여 전파를 추적하는 것입니다.경우에 따라 null 포인터 예외를 수정하기 [10]위한 패치를 자동으로 생성할 수 있습니다.

순수 기능 언어 및 다수의 인터프리터 언어 또는 가상 머신 언어로 실행되는 사용자 코드는 포인터에 대한 직접 액세스가 제공되지 않으며 순수 기능 언어의 경우 모든 코드와 데이터는 불변하기 때문에 늘 포인터 참조의 문제를 겪지 않습니다.

언어가 무효가 될 수 있는 포인터를 제공하거나 사용하는 경우 정적 분석 또는 기타 기술을 통해 컴파일 시간 체크를 제공함으로써 런타임의 늘 유기를 완화하거나 방지할 수 있으며, 이는 최신 버전의 언어 기능에서 볼 수 있는 구문적 지원을 향한 움직임으로 급성장하고 있다.에펠 프로그래밍 [11]언어[12]D와 Rust.[13]

일부 언어에서는 외부 도구를 사용하여 유사한 분석을 수행할 수 있습니다.

역사

2009년 토니 호어[14] 경은 1965년 ALGOL W 언어의 일부로 Null 참조를 발명했다고 밝혔다.2009년 참조 자료에서 Hoare는 자신의 발명을 "억 달러의 실수"라고 표현했습니다.

나는 그것을 10억 달러의 실수라고 부른다.그것은 1965년에 무효표시가 발명된 것이다.그 때, 저는 오브젝트 지향 언어(ALGOL W)의 레퍼런스를 위한 최초의 종합형 시스템을 설계하고 있었습니다.제 목표는 모든 참조를 안전하게 사용하고 컴파일러에 의해 자동으로 확인되도록 하는 것이었습니다.하지만 나는 단지 그것이 실행하기에 너무 쉽다는 이유로, 불필요한 참조를 넣으려는 유혹을 뿌리칠 수 없었다.이로 인해 수많은 오류, 취약성 및 시스템 충돌이 발생했으며, 이는 지난 40년간 10억 달러의 고통과 피해를 야기했을 것입니다.

「 」를 참조해 주세요.

레퍼런스

인용문

  1. ^ ISO/IEC 9899, 조항 6.3.2.3, 단락 4.
  2. ^ ISO/IEC 9899, 조항 7.17, 단락 3: 구현 정의 Null 포인터 상수로 확장되는 NULL...
  3. ^ ISO/IEC 9899, 조항 6.3.2.3, 단락 3.
  4. ^ a b ISO/IEC 9899, 조항 6.5.3.2, 단락 4, 특히 각주 87.
  5. ^ Stroustrup, Bjarne (March 2001). "Chapter 5:
    The const qualifier (§5.4) prevents accidental redefinition of NULL and ensures that NULL can be used where a constant is required.". The C++ Programming Language (14th printing of 3rd ed.). United States and Canada: Addison–Wesley. p. 88. ISBN 0-201-88954-4.
  6. ^ Objective-C 2.0 프로그래밍 언어 섹션 "메시지 0으로 보내기"
  7. ^ AppleGraphicsDeviceControl의 OS X 공격 가능한 커널 NULL 포인터 참조 해제
  8. ^ a b Bond, Michael D.; Nethercote, Nicholas; Kent, Stephen W.; Guyer, Samuel Z.; McKinley, Kathryn S. (2007). "Tracking bad apples". Proceedings of the 22nd annual ACM SIGPLAN conference on Object oriented programming systems and applications - OOPSLA '07. p. 405. doi:10.1145/1297027.1297057. ISBN 9781595937865. S2CID 2832749.
  9. ^ a b Cornu, Benoit; Barr, Earl T.; Seinturier, Lionel; Monperrus, Martin (2016). "Casper: Automatic tracking of null dereferences to inception with causality traces". Journal of Systems and Software. 122: 52–62. arXiv:1502.02004. doi:10.1016/j.jss.2016.08.062. ISSN 0164-1212.
  10. ^ Durieux, Thomas; Cornu, Benoit; Seinturier, Lionel; Monperrus, Martin (2017). "Dynamic patch generation for null pointer exceptions using metaprogramming" (PDF). 2017 IEEE 24th International Conference on Software Analysis, Evolution and Reengineering (SANER). IEEE: 349–358. arXiv:1812.00409. doi:10.1109/SANER.2017.7884635. ISBN 978-1-5090-5501-2. S2CID 2736203.
  11. ^ "Void-safety: Background, definition, and tools". Retrieved 2021-11-24.
  12. ^ Bartosz Milewski. "SafeD – D Programming Language". Retrieved 17 July 2014.
  13. ^ "Fearless Security: Memory Safety". Archived from the original on 8 November 2020. Retrieved 4 November 2020.
  14. ^ Tony Hoare (2009-08-25). "Null References: The Billion Dollar Mistake". InfoQ.com.

원천