C ++ - 安全指针范围?

时间:2012-10-07 12:06:22

标签: c++ pointers

我知道null(0x00000000)是指向无点的,因为操作系统不允许进程在这里分配内存。但是如果我使用0x00000001(幻数或代码指针),操作系统不允许在这里分配它也是安全的吗? 如果是,那么它停在哪里?

6 个答案:

答案 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)

我会尝试对此提出一个广泛的看法:

  1. 你可能永远不会访问真实的内存地址,因为每个现代操作系统都有多个沙盒机制并且已经到位。
  2. 从软件角度来看,什么是NULL指针? NULL指针是一个指针变量,它存储程序员选择作为有意义的值的值,该值用作具有以下含义的标签“this pointer goes wherehere”。根据定义,NULL指针不指向0x000000,NULL指针的定义与指针所指向的位置无关,但此宏的值称为NULL,此值将是此NULL指针的值。
  3. 在C中你可以假设NULL == 0,只有在C NULL中是一个宏,它将NULL定义为一个等于0的int,在C ++中你没有这个自由
  4. 对于每个变量都有类型,标签和值(更好地说,值的表示而不是实数值),至少对于基元值,对于指针也是如此,如果你在谈论你正在谈论的无效指针包含内存地址的指针(就像任何指针一样),这个指针的唯一特殊之处在于它们需要C ++中的强制转换才能安全有效地进行解码;如果您将void*视为指向无处或指向0NULL0x0000000
  5. 的指针,那将是一个很大的错误 顺便说一下,我仍然没有解决你的问题...

答案 5 :(得分:0)

现代操作系统可能会为NULL指针保留至少一个页面。所以0x1(如果想要32位对齐,则为0x4)可能会起作用。

但请记住,C / C ++语言无法保证这一点。你必须依靠你的操作系统和编译器来做这种行为。

此外,无法保证NULL指针的实际值。它可能全部为零,也可能不是全零。如果不是,那么你的伎俩根本不起作用。