문제

ANSI C89/ISO C90에서 공극 포인터 값에 대한 상부 및 하한을 포장 적으로 결정하는 방법이 있습니까? (현재 나와 함께 표준 사본이 없습니다 (집에 하나가 있습니다). 물론 Void-Pointer 값이 서명되지 않은 경우이 작업은 사소합니다 (Sizeof (void *)); 이것이 보장되는지 여부를 상기하십시오. 나는 매우 비효율적 인 알고리즘 (오버플로까지 증가)을 생각할 수 있지만, 누군가가 비교적 저렴한 (시간 복잡성 측면에서)와 휴대용 방법을 가지고 있는지 알고 싶습니다. 이 경계를 계산하십시오.)

--편집하다--

또한: 포인터 값의 유효성을 결정하는 휴대용 방법이 있습니까?

왜: 이것은 동료와의 토론에서 나왔고 그것은 나를 괴롭 혔습니다. 나는 그가 무엇을하고 있는지 모르겠지만, 나는 관심이 있기 때문에 알고 싶다! :-)

도움이 되었습니까?

해결책

주어진 포인터가 유효한지 여부를 결정하는 휴대용 방법이 없습니다. 어떤 종류의 메모리 시스템을 다루고 있는지 알아야합니다. 운영 체제 및 프로세서에 따라 가상 메모리 관리자의 페이지 테이블을 쿼리하여 유효한 포인터 범위를 결정하는 방법이 있거나 아닐 수도 있습니다.

예를 들어 Linux에서는 특별한 것을 검사 할 수 있습니다. mmap 아래에 파일 /proc 프로세스의 가상 메모리 맵을 얻습니다. 다음은 다음과 같습니다 cat 자체 메모리지도 읽기 :

$ cat /proc/self/mmap
08048000-0804c000 r-xp 00000000 09:00 5128276                            /bin/cat
0804c000-0804d000 rw-p 00003000 09:00 5128276                            /bin/cat
0804d000-0806e000 rw-p 0804d000 00:00 0                                  [heap]
f7ca7000-f7e40000 r--p 00000000 09:00 3409654                            /usr/lib/locale/locale-archive
f7e40000-f7e41000 rw-p f7e40000 00:00 0 
f7e41000-f7f68000 r-xp 00000000 09:00 2654292                            /lib/tls/i686/cmov/libc-2.3.6.so
f7f68000-f7f6d000 r--p 00127000 09:00 2654292                            /lib/tls/i686/cmov/libc-2.3.6.so
f7f6d000-f7f6f000 rw-p 0012c000 09:00 2654292                            /lib/tls/i686/cmov/libc-2.3.6.so
f7f6f000-f7f72000 rw-p f7f6f000 00:00 0 
f7f83000-f7f85000 rw-p f7f83000 00:00 0 
f7f85000-f7f9a000 r-xp 00000000 09:00 2637871                            /lib/ld-2.3.6.so
f7f9a000-f7f9c000 rw-p 00014000 09:00 2637871                            /lib/ld-2.3.6.so
ff821000-ff836000 rw-p 7ffffffea000 00:00 0                              [stack]
ffffe000-fffff000 r-xp ffffe000 00:00 0                                  [vdso]

메모리가 (r) eadable, (w) Ritable, e (x) Ecutable, 또는 (p) 분개 여부를 나타내는 비트와 함께 유효한 포인터의 범위를 볼 수 있습니다.

다른 팁

SPEC에 의해 서명되지 않도록 포인터는 보장됩니다. 그러나 왜 지구상에서 한계를 찾고 싶습니까? "0x00000001과 0xffffffffff 사이의 모든 것은"실제로 유용한 테스트가 아닙니다. 유효한 포인터는 그것의 작은 하위 집합이 될 것입니다.

void *는 항상 주소 지정 가능한 메모리에 대한 포인터를 잡을만큼 충분히 큽니다. 메이저 리그 야구 협회는 다른 용도로 엄격히 금지됩니다.

예 : 12 월 10 일은 36 개의 비트 단어가있는 36 비트 아키텍처였습니다. 그러나 주소는 18 비트였으며 모든 레지스터/단어로 2 개의 포인터를 보유 할 수 있습니다.

예 - 그것은 극단적 인 예입니다. 포인터로 수학을해야한다면 크기가 유효합니다. 그러나 인접한 배열 이외의 다른 것에서 포인터 수학을하는 것은 Dodgy보다 더 거칠다.

마지막으로 - 'void *'를 사용하여 C ++의 객체 또는 포인터에 대한 포인터를 저장하지 마십시오. 많은 컴파일러 구현은 실제로 여러 '물리적'포인터를 사용하여 콘크리트 (또는 부분 콘크리트) 클래스의 여러 유전을 구현합니다. 실제로 이것은 거의 거의 나오지 않습니다. 왜냐하면 이런 식으로 여러 상속을 사용하는 사람은 거의 없으며, 그렇게 할 때는 거의 슬라이스와 unlice 포인터가 거의 없습니다. 그것이 나타나면 무슨 일이 있었는지 알아 내기가 정말 어렵습니다.

정수 가치를 식별해야합니다. void * 메모리의 실제 비트 패턴에서 캐스트 할 수 있습니다 - 캐스팅 void * 정수 유형에는 변환이 포함될 수 있습니다!

가정합니다 sizeof(void *) == sizeof(long), a void * p 다음은 거짓일 수 있습니다.

((long)p) == *((long *)&p)

또한 표준은 거기에 있는지 여부를 지정하지 않습니다 ~이다 모든 유효한 포인터의 값을 유지하기에 충분히 큰 정수 유형!

그러므로, 당신이하고 싶은 일을 할 수있는 휴대용 방법은 없습니다 ...

NULL에 해당하는 영역 외에도 메모리 주소에 전혀 휴대용 제한이 없습니다. 충분히 경화 된 OS는 다양한 CPU/OS 메커니즘을 활용하여 각 프로세스가 Malloc ()에 대한 각 호출과 함께 무작위 및 잘 분산 된 주소를 제공 할 수 있으며, 독립적 인 실행 파일 Plus ASLR을 포지션하면 코드가 모든 주소에서 실행될 수 있습니다.

Win32에서 64 비트 포인터가 표시되어 있음을 알고 있습니다. 연장 포인터에 서명하지 않으면 64 비트 기계에서 32 비트 미니 덤프를 검사하는 것이 재미 있습니다.

보다 여기 64 비트 포인터 (POINTER_64) Win32에서 작동합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top