【问题标题】:range of values a c pointer can take?c指针可以取的值范围?
【发布时间】:2014-02-17 03:34:35
【问题描述】:

在“计算机系统:程序员的视角”第 2.1 节(第 31 页)中,它说:

C 中指针的值是某个存储块的第一个字节的虚拟地址。

在我看来,C 指针的值可以取 0 到 [虚拟内存大小 - 1] 之间的值。是这样吗?如果是,我想知道是否有任何机制可以检查程序中的所有指针是否都分配了合法值——值至少为 0,最多为 [虚拟内存大小 - 1],以及这种机制的内置位置——在编译器中?操作系统?还是其他地方?

【问题讨论】:

  • 我认为是通过指针的大小来确定的,在32位系统中,指针的大小是4bytes,虚拟内存是2^32,所以它总是有效的?
  • 合法值是实现和操作系统特定的。为了完成你所寻求的需要一个系统,它确实知道每个指针在你的运行代码中的位置。大多数分析器寻找有效的指针因为字节序列是一个有效的内存偏移),但有非常几个平台(我只能想一想)实际知道存储在进程内存中特定位置的值是否是(a)指针,并且(b)持有有效地址。
  • 指针可以取任何有效值。但是“有效”在很多方面都有限定。零是有效的,但 1 肯定不是。一些范围是有效的,而另一些则不是,这取决于分配给进程的地址范围。偶数地址可能有效,奇数无效,具体取决于架构细节。
  • @WhozCraig - Java 的某些版本知道哪些特定位置是指针,哪些不是,但在 C 中几乎不可能。
  • @HotLicks 如果在内核级别完成,这很困难,但并非不可能。一个 AS/400 可以做到这一点(我能想到的一个平台),说它是非凡的将是对史诗比例的轻描淡写。

标签: c++ c pointers system


【解决方案1】:

没有任何进程检查指针的有效性,因为使用无效指针无论如何都会产生未定义的影响。

通常,指针不可能保存可寻址范围之外的值,因为两者将具有相同的可用范围——例如两者都是 32 位的。然而,一些 CPU 有关于指针对齐的规则,这可能会使某些地址对某些类型的数据无效。一些运行时,例如 64 位 Objective-C,它是 C 的严格超集,使用错误对齐的指针将字面量对象伪装成堆上的对象。

在某些情况下,完整的地址空间由指令集定义为一件事,但由特定硬件实现为另一件事。历史上的一个例子是最初的 68000,它定义了一个 32 位空间,但只有 24 条地址线。非常早期的 Mac OS 版本使用备用的 8 位来描述数据块的标志,依靠硬件来忽略它们。

所以:

  • 没有运行时有效性检查;
  • 即使有,有效性的含义通常取决于 CPU 的特定型号(不仅仅是系列)或操作系统的特定版本(同上),以使检查变得比您想象的更简单。

在实践中,如果您的地址对于该硬件来说是非法的,但被访问时就像合法是处理器异常一样,通常会发生什么。

【讨论】:

    【解决方案2】:

    C 中的指针是一个抽象对象。 C 标准提供的唯一保证是指针可以指向它们在 C 中需要指向的所有内容:函数、对象、对象末尾之后的一个以及 NULL。

    在典型的 C 实现中,指针可以指向虚拟内存中的任何地址,并且一些 C 实现在很大程度上故意支持这一点。然而,也有并发症。例如,用于 NULL 的值可能难以用作地址,并且为一种类型创建的指针转换为另一种类型可能会失败(由于对齐问题)。此外,还有一些合法的非典型 C 实现,其中指针不以正常方式直接关联到内存地址。

    在不了解 C 标准和您使用的 C 实现的规则的情况下,您不应期望使用指针来任意访问内存。

    C 中没有检查程序中的指针是否有效的机制。程序员有责任正确使用它们。

    【讨论】:

      【解决方案3】:

      出于实际目的,C 指针要么是 NULL,要么是指向其他对象的内存地址。我从来没有听说过 NULL 在现实生活中不是零。如果它是一个内存地址,那么您不应该“关心”实际数字是多少;只是传递它,取消引用它等等。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-09-30
        • 2022-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-26
        • 1970-01-01
        相关资源
        最近更新 更多