【问题标题】:How does the system knew that an address being accessed is constant or not系统如何知道正在访问的地址是否为常量
【发布时间】:2016-08-24 05:44:57
【问题描述】:

使用指针写入常量变量会导致运行时错误。

const int i;
int *p;
void main()
{
    p = (int*)&i;
    *p = 10;         // Causes runtime error
}

但在 Windows 系统中,一切都是从 RAM 本身运行的。

当我打印const变量和普通变量的地址时,我可以看到它们在不同的偏移量中。

系统如何知道指针所访问的地址是const 1?

【问题讨论】:

  • 链接器已将全局变量 i 放在可执行映像的 RO 部分中。
  • *p = 10 个未定义的行为。

标签: c pointers constants


【解决方案1】:

严格来说,根据 C 语言标准,您的代码会产生未定义的行为。

实际上,链接器可能已将变量 i 放在可执行映像的 RO 部分中。

所以写操作*p = 10 导致了内存访问冲突(又名分段错误)。

【讨论】:

  • RO 部分是否驻留在 RAM 中?
  • @AbleEldhose:我这里的其余评论不是由 C 语言标准规定的,而是基本上取决于底层平台(操作系统、虚拟内存、编译器、链接器等) .通常,整个可执行映像被加载到 RAM 中。有时它的一部分可能会“换出”到硬盘中,以便为其他应用程序“腾出空间”。但基本上,当它运行时 - 它是从 RAM 运行的(同样,取决于您的平台 - 例如,有些硬件架构可以从 Flash 运行所有内容)。
  • 当可执行映像从 RAM 运行时,为该映像中的不同部分定义了不同的访问权限。例如,代码部分肯定是 RO。堆栈是 RW。数据部分(全局和/或静态变量)通常分为 RO 和 RW。但这并不像 RO 部分实际上驻留在“物理” RO 存储单元中。只是任何内存访问尝试都会通过 MMU(内存管理单元),如果尝试非法,则会引发总线故障异常。
【解决方案2】:

系统是怎么知道的......

理想情况下,系统不需要知道。对于具有const-qualified 类型的对象,分配(通常)将位于只读部分,因此任何修改(写入)的尝试都会导致访问冲突。程序员应该知道。

当我打印const变量和普通变量的地址时,我可以看到它们在不同的偏移量中。

是的,这很可能,因为 normal 变量驻留在读写内存中,而 const 变量将驻留在只读内存中。

请注意,您的代码 sn-p 没有没有语法(或编译)错误。只是代码的行为(运行时)是未定义的。

仅供参考,引用 C11,第 §6.7.3/p6 章

如果尝试通过使用来修改使用 const 限定类型定义的对象 具有非 const 限定类型的左值,行为未定义。 [...]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 2017-06-23
    • 2015-08-15
    • 1970-01-01
    相关资源
    最近更新 更多