我知道null
(0x00000000)是指向无点的,因为操作系统不允许进程在这里分配内存。但是如果我使用0x00000001(幻数或代码指针),操作系统不允许在这里分配它也是安全的吗?
如果是,那么它停在哪里?
答案 0 :(得分:4)
标准(第一个)
标准只保证0
是指针的哨兵值。底层的内存表示无法保证;它的实现已定义。
使用指向该sentinel值的指针除了读取指针状态或写入新状态(包括解除引用或指针算术)之外的其他任何内容都是未定义的行为。
虚拟内存
在虚拟内存的时代(即,每个进程获得自己的内存空间,独立于其他进程),空指针通常在进程内存空间中实际上表示为0。我实际上并不了解任何其他架构,但我想在大型机中它可能不是这样。
<强>的Unix 强>
在Unix世界中,通常将空值保留在0x8000以下的所有地址空间。内存未分配,实际上,它只是受到保护(即,处于特殊模式),因此如果您尝试读取或写入操作系统,操作系统将触发分段错误。
使用这样一个范围的想法是不一定按原样使用空指针。例如,如果使用null std::pair<int, int>* p = 0;
并调用p->second
,则编译器将执行必要的算术以指向second
(通常为+4
)并尝试直接访问0x4
的内存。这个问题显然因数组而复杂化。
实际上,此0x8000
限制应足以检测大多数问题(并避免内存损坏或其他问题)。在这种情况下,这意味着您可以避免未定义的行为并获得正确的&#34;崩溃。但是,如果你使用大型阵列,你可能会超过它,所以它不是一颗银弹。
您的实现或编译器/运行时堆栈的特定限制可以通过文档或连续试验来确定。甚至可能有一种方法来调整它。
答案 1 :(得分:2)
你不应该假设指针的实际值。特别是,空指针不需要由零地址表示,即使文字0
看起来像零。
答案 2 :(得分:1)
唯一有效的范围应该是操作系统为您分配的范围。操作系统应拒绝其他任何操作。
该规则的一个例外是共享内存。
答案 3 :(得分:1)
C ++标准不会“保留”除零(null)以外的任何指针地址。因此,使用1或任何其他值作为“魔法”指针值是不安全的。当然,在实践中,c ++的某些实现可能并不是每个都使用某些值。但是你没有得到语言定义的任何保证。
答案 4 :(得分:0)
我会尝试对此提出一个广泛的看法:
NULL == 0
,只有在C NULL中是一个宏,它将NULL定义为一个等于0的int,在C ++中你没有这个自由void*
视为指向无处或指向0
或NULL
或0x0000000
答案 5 :(得分:0)
现代操作系统可能会为NULL指针保留至少一个页面。所以0x1(如果想要32位对齐,则为0x4)可能会起作用。
但请记住,C / C ++语言无法保证这一点。你必须依靠你的操作系统和编译器来做这种行为。
此外,无法保证NULL指针的实际值。它可能全部为零,也可能不是全零。如果不是,那么你的伎俩根本不起作用。