gpt4 book ai didi

c - 符合C标准的方法来访问空指针地址?

转载 作者:太空狗 更新时间:2023-10-29 16:22:35 29 4
gpt4 key购买 nike

在C语言中,将空指针延迟是未定义行为,但是空指针值具有位表示形式,在某些体系结构中,空指针值使其指向有效地址(例如地址0)。
为了清楚起见,我们将此地址称为空指针地址。

假设我想在不受限制地访问内存的环境中用C编写一个软件。进一步假设我想在空指针地址处写入一些数据:我将如何以符合标准的方式实现这一目标?

示例案例(IA32e):

#include <stdint.h>

int main()
{
uintptr_t zero = 0;

char* p = (char*)zero;

return *p;
}

当使用带有-O3的IA32e的gcc编译时,此代码会转换为
movzx eax, BYTE PTR [0]
ud2

由于UB(0是空指针的位表示)。

由于C接近于底层编程,因此我相信必须有一种访问空指针地址并避免UB的方法。

只是为了清楚
我问的是标准对此要说些什么, 而不是如何以实现定义的方式实现这一点。
我知道后者的答案。

最佳答案

我阅读了C99标准(的一部分)以明确自己的想法。我找到了自己的问题感兴趣的部分,并将其作为引用。

免责声明
我是个绝对的初学者,我写的内容中有90%或更多是错误的,毫无道理的,或者可能会破坏您的烤面包机。我还尝试以超出标准的理由,通常会带来灾难性和幼稚的结果(如评论中所述)。
不要看
请咨询@Olaf,以获得正式且专业的答案。

对于以下内容,术语“架构地址”设计了一个处理器可以看到的存储器地址(逻辑,虚拟,线性,物理或总线地址)。换句话说,您将在汇编中使用的地址。

在6.3.2.3节中。它读

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.



关于整数到指针的转换

An integer may be converted to any pointer type. Except as previously specified [i.e. for the case of null pointer constant], the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.



这意味着要兼容,编译器仅需要实现从整数到指针的函数int2ptr

根据定义,
  • int2ptr(0)是空指针
    请注意,int2ptr(0)未强制为0。它可以是任何位表示形式。
  • * int2ptr(n!= 0)没有约束。
    注意,这意味着int2ptr不必是恒等函数,也不必是返回有效指针的函数!

  • 鉴于以下代码
    char* p = (char*)241;

    该标准绝对不保证表达式 *p = 56;将写入架构地址241。
    因此,它无法直接访问任何其他体系结构地址(包括int2ptr(0),即由空指针设计的地址,如果有效)。

    简而言之,该标准不涉及体系结构地址,而是涉及指针,它们的比较,转换及其操作‡。

    当我们编写类似 char* p = (char*)K的代码时,我们并不是在告诉编译器使 p指向 建筑地址 K,而是在告诉它使指针指向整数K之外,或者换句话说,就是使 p指向(C摘要)地址K。

    空指针和(架构)地址0x0不相同(引用),因此对于由整数K和(架构)地址K构成的任何其他指针也是如此。

    出于某种原因,从小时候起,我就认为C中的整数可以用来表示体系结构地址,而不是 我错了,并且在我使用的编译器中恰好是(某种)正确的。

    我自己的问题的答案很简单: 没有标准方法,因为C标准文档中没有(体系结构)地址。对于每个(体系结构)地址都是如此,不仅是int2ptr(0)one1。

    关于return *(volatile char*)0;的说明

    标准说

    If an invalid value [a null pointer value is an invalid value] has been assigned to the pointer, the behavior of the unary * operator is undefined.



    然后

    Therefore any expression referring to such an [volatile] object shall be evaluated strictly according to the rules of the abstract machine.



    抽象机器说,对于空指针值, *是未定义的,因此代码不应与此代码有所不同
    return *(char*)0;
    这也是未定义的。
    的确,它们至少在GCC 4.9中没有区别,两者均按照我的问题中所述的说明进行编译。

    对于GCC,实现定义的访问0架构地址的方式是使用-fno-isolate-er错误路径-解除引用标志,该标志会产生“预期的”汇编代码。

    †用于将指针转换为整数或将整数转换为指针的映射功能旨在
    与执行环境的寻址结构一致。

    ‡很遗憾,它说 &产生其操作数的地址,我相信这有点不正确,我想说它产生一个指向其操作数的指针。考虑一个已知存在于16位地址空间中地址0xf1的 a变量,并考虑一个实现int2ptr(n)= 0x8000 | | |的编译器。 。 &a将产生一个指针,其位表示为0x80f1,即 而不是a的地址

    1这对我来说很特别,因为在我的实现中,它是唯一无法访问的。

    关于c - 符合C标准的方法来访问空指针地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35537579/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com