有没有办法可移植判断上,在ANSI C89 / ISO C90上的空指针值下限?(我目前还没有与我的标准的复印件(我有。一个人在家),当然,如果无效指针值,保证是无符号这个任务是微不足道的(通过的sizeof(无效*));但是,如果这是保证或不是我不记得我能想到的几个非常低效的算法(增量直到溢出等),但我想知道如果任何人有来计算这些边界相对便宜的(在时间复杂度而言)和可移植的方式。)

- 编辑 -

同时是否有便携的方式来确定指针值的有效性

为什么:这与同事讨论出来的,它难倒我。我不知道他的工作,但我只是想知道,因为我很感兴趣! : - )

有帮助吗?

解决方案

没有可移植的方法,以确定是否一个给定的指针是有效还是无效。你必须知道你正在处理什么样的存储系统的使用。根据操作系统和处理器上,也有可能是或可能不是查询虚拟内存管理器的页表,以确定指针的有效范围的一种方式。

例如,在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)的重发(即,不调出到磁盘)

其他提示

指针由规格保证是无符号的。但是,为什么在地球上你想找到的界限? “00000001和0xffffffff的一切之间”是不是一个真正的有用的测试中,由于数量的有效指针将是那一些微小的子集。

无效*总是大到足以容纳一个指针寻址存储器。任何其它使用严格受棒球大联盟关联禁止。

例:癸10是36位结构体系的36个字。然而,地址是18位,你可以在任一寄存器/字保持2个指针。

是的 - 这是一个极端的例子。如果你必须做的指针数学的sizeof是有效的;但在除一个连续数组以外的任何操作的方式指针数学比躲闪dodgier。

最后 - 永不使用“无效*”的指针的对象或存储指向构件在C ++中。许多编译器实现实际上使用多个“物理”指针来实现混凝土(或部分混凝土)类的多重的传承。在现实中,这是因为很少有人使用多重继承这种方式,当他们这样做,很少切片和unslice指针几乎从来没有出现。当它出现,这真的很难搞清楚发生了什么事。

您必须辨别哪个一个void *可以从存储器中的实际的位模式被转换为整数值! - 铸造void *为整数类型可以涉及转换

假设sizeof(void *) == sizeof(long),对于void * p以下可能是假的:

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

此外,该标准没有具体说明是否连的的整数型大到足以容纳所有有效指针的值!

因此,恰恰是没有可移植的方法去做你想做的事......

除了对应于NULL的区域中,存在对存储器地址没有(便携式)限制在所有。甲充分硬化OS可以利用各种CPU / OS的机制来提供具有随机和均匀分布的地址的每个进程与每个呼叫对malloc(),并且与位置无关的可执行加ASLR可允许代码从任意地址上运行。

我知道在Win32,64位指针是符号扩展。它的乐趣,从64位机检查32位转储,如果你不签延长指针。

请参阅此处如何64位指针(POINTER_64)工作在Win32。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top