programing

NULL 재정의

nicescript 2022. 12. 29. 22:02
반응형

NULL 재정의

주소 0x0000이 유효하고 포트 I/O가 포함된 시스템의 C 코드를 쓰고 있습니다.따라서 NULL 포인터에 액세스하는 버그는 검출되지 않은 채 위험한 동작을 일으킵니다.

이러한 이유로 NULL을 다른 주소(예: 유효하지 않은 주소)로 재정의하고 싶습니다.이러한 주소에 잘못 액세스 했을 경우, 에러를 처리할 수 있는 하드웨어 인터럽트가 발생합니다.이 컴파일러의 stdef.h에 액세스 할 수 있게 되어, 실제로 표준 헤더를 변경해, NULL을 재정의할 수 있습니다.

질문이 있습니다.이것이 C기준과 모순되는가?표준 7.17부터의 매크로는 구현 정의되어 있습니다.표준에는 NULL이 0이어야 한다고 기재되어 있는 것이 있습니까?

또 다른 문제는 많은 컴파일러가 데이터 유형에 관계없이 모든 것을 0으로 설정하여 정적 초기화를 실행한다는 것입니다.표준에서는 컴파일러가 정수를 0으로 설정하고 포인터를 NULL로 설정하도록 되어 있지만, 컴파일러의 NULL을 다시 정의하면 이러한 정적 초기화가 실패할 것을 알고 있습니다.컴파일러 헤더를 수동으로 과감하게 변경했는데 컴파일러 동작이 잘못된 것으로 간주할 수 있습니까?이 컴파일러는 스태틱 초기화를 실행할 때 NULL 매크로에 액세스하지 않는다는 것을 확실히 알고 있기 때문입니다.

C c 0 에 null 。 캐스팅 a, casting a0에는 반드시 '지시하다'가 .NULLnull 포인터를 부울로 평가하는 것은 false여야 합니다.주소를 0으로 하고 싶은 경우는, 조금 곤란할 가능성이 있습니다.NULL제로 주소가 아닙니다.

의 ( 컴파일러와 표준 라이브러리의 (중요한) 변경이 NULL표준 라이브러리에 엄밀하게 준거한 채 대체 비트 패턴으로 표현됩니다.단순히 의 정의를 변경하는 만으로는 충분하지 않습니다.NULL, 그 NULL사실로 평가될 것입니다.

구체적으로는, 다음과 같이 할 필요가 있습니다.

  • 포인터에 또는 포인터에 캐스트)에서을를 들어, 「0」은 「0」이 됩니다.-1.
  • 와 합니다.0하다 (6)
  • 포인터 유형이 부울로 평가되는 모든 컨텍스트에 대해 정렬하여 0을 확인하는 대신 매직 값과 동일한지 확인합니다.이는 동등성 테스트의 의미론에서 따르지만 컴파일러는 내부적으로 다르게 구현할 수 있습니다.'6.5.13/3, '6.5.14/3, '6.5.15/4', '6.5.3/5, '6.8.4.1/2, '6.8.5/4'를 참조해 주세요.
  • 카페가 지적한 바와 같이 정적 객체( (6.7.8/10)와 부분 복합 이니셜라이저(66.7.8/21)의 초기화를 위한 시멘틱스를 업데이트하여 새로운 늘 포인터 표현을 반영합니다.
  • 실제 주소 0에 액세스하는 대체 방법을 만듭니다.

당신이 처리할 필요가 없는 것들이 있습니다.예를 들어 다음과 같습니다.

int x = 0;
void *p = (void*)x;

후에, 「 」는 「 」의p는 늘 포인터임을 보증하지 않습니다.상시 할당만 처리하면 됩니다(이것은 진정한 주소 0에 액세스하기 위한 적절한 접근법입니다.★★★★★★★★★★★★★★★★★★:

int x = 0;
assert(x == (void*)0); // CAN BE FALSE

기타:

void *p = NULL;
int x = (int)p;

x는 보증되지 않습니다.0.

간단히 말해, 이 조건은 C 언어 위원회에서 고려된 것으로 보이며, NULL을 대신하는 표현을 선택하는 사람들에 대한 고려 사항입니다.지금 해야 할 일은 컴파일러에 큰 변경을 가하는 것뿐입니다.이러면 완료입니다.

한편, 컴파일러가 제대로 동작하기 전에 소스 코드 변환 단계를 사용하여 이러한 변경을 구현할 수 있습니다.즉, 프리프로세서 -> 컴파일러 -> 어셈블러 -> 링커의 일반적인 흐름 대신 프리프로세서 -> NULL 변환 -> 컴파일러 -> 어셈블러 -> 링커를 추가합니다.그런 다음 다음과 같은 변환을 수행할 수 있습니다.

p = 0;
if (p) { ... }
/* becomes */
p = (void*)-1;
if ((void*)(p) != (void*)(-1)) { ... }

여기에는 어떤 식별자가 포인터에 대응하는지 판단하기 위해 타입 파서와 타입 파서가 필요합니다.그러나 이렇게 함으로써 컴파일러의 코드 생성 부분을 적절히 변경할 필요가 없어집니다.clang은 이 기능을 구현하는 데 도움이 될 수 있습니다.이러한 변환을 염두에 두고 설계된 것으로 알고 있습니다.물론 표준 라이브러리도 변경해야 합니다.

0으로 된 되어 있습니다.void *늘 상수입니다.type은 포인터 상수입니다., ,,(void *)0늘 입니다만, 「」가 지정됩니다.int i = 0;,(void *)i그럴 필요가 없다.

c c c c c c c c c c c c c.하여 " " " 를 재정의하는 NULL단, 정적 초기화를 수정하기 위해 컴파일러를 수정하지 마십시오.그러면 중단되지 않는 구현을 작성하게 됩니다. 것은 이며, 할 수

.p,if (p) if (p != NULL)츠요시

C std 라이브러리를 사용하는 경우 NULL을 반환할 수 있는 함수에 문제가 발생합니다. 예를 들어 malloc 문서에는 다음과 같이 기술되어 있습니다.

함수가 요청된 메모리 블록을 할당하지 못한 경우 늘 포인터가 반환됩니다.

malloc 및 관련 함수는 이미 특정 NULL 값을 가진 바이너리로 컴파일되어 있기 때문에 NULL을 재정의하면 C std libs를 포함한 툴 체인 전체를 재구축할 수 없는 한 C std 라이브러리를 직접 사용할 수 없습니다.

또한 std 라이브러리는 NULL을 사용하기 때문에 std 헤더를 포함하기 전에 NULL을 재정의하면 헤더에 나열된 NULL 정의를 덮어쓸 수 있습니다.삽입된 항목은 컴파일된 개체와 일치하지 않습니다.

대신 사용자 자신의 사용을 위해 사용자 자신의 NULL인 "MYPRODUCT_NULL"을 정의하고 C std 라이브러리에서 변환하지 않도록 합니다.

다른 사용자가 언급한 것처럼 NULL을 재정의하는 것이 매우 어렵다는 점을 고려하면 잘 알려진 하드웨어 주소에 대한 참조를 재정의하는 이 더 쉬울 수 있습니다.주소를 작성할 때 모든 기존 주소에 1을 추가하여 기존 IO 포트가 다음과 같이 되도록 합니다.

  #define CREATE_HW_ADDR(x)(x+1)
  #define DEREFERENCE_HW_ADDR(x)(*(x-1))

  int* wellKnownIoPort = CREATE_HW_ADDR(0x00000000);

  printf("IoPortIs" DEREFERENCE_HW_ADDR(wellKnownIoPort));

관심 있는 주소가 함께 그룹화되어 있고 주소에 1을 추가하는 것이 충돌하지 않는다고 안심할 수 있는 경우(대부분의 경우) 이 작업을 안전하게 수행할 수 있습니다.툴 체인/std lib 및 표현식을 다음과 같은 형식으로 재구축하는 것에 대해 걱정할 필요가 없습니다.

  if (pointer)
  {
     ...
  }

아직 일하지 않다

말도 안 되는 건 알지만, 그냥 아이디어를 던져버리려고 했어요.

NULL은 그대로 두고 포트 0x0000에 대한 IO는 어셈블러에서 작성된 루틴을 사용하여 특별한 경우로 취급합니다.따라서 표준 C 시멘틱스의 대상이 되지 않습니다.IOW, NULL을 재정의하지 않고 포트 0x00000을 재정의합니다.

C 컴파일러를 쓰거나 변경할 경우 NULL을 참조하지 않기 위해 필요한 작업은 NULL이 어떻게 정의되어 있는지에 관계없이 동일합니다.따라서 NULL을 0으로 정의하여 C에서 참조되지 않도록 하는 것이 더 쉽습니다.

당신은 문제를 일으키고 있어요.재정의NULL이 코드가 해제됩니다.

if (myPointer){// myPointer가 null이 아닙니다....
}

늘 포인터의 비트 패턴은 정수0의 비트 패턴과 다를 수 있습니다.단, NULL 매크로의 확장은 (void*)에 캐스트할 수 있는 값 0의 정수인 늘 포인터 상수여야 합니다.

적합성을 유지하면서 원하는 결과를 얻으려면 도구 체인을 수정(또는 구성)해야 하지만 실현 가능합니다.

언급URL : https://stackoverflow.com/questions/5142251/redefining-null

반응형