是否可以访问物理地址0?

时间:2014-11-04 13:00:04

标签: c++ c assembly operating-system x86

在C / C ++中,不允许访问地址0处的数据。

然而,物理内存从0开始编号。在DOS时代,中断向量表位于物理地址0处。第一个中断向量是除零异常的处理程序。

我的问题是:

在什么情况下允许访问物理地址0?

6 个答案:

答案 0 :(得分:8)

要访问物理地址零,取决于您正在谈论的平台。 语言不了解底层寻址模型,它取决于操作系统。

  • 在裸机环境中,如果启用了分页,则可以完全控制页表;如果未启用分页,则只需取消引用零。
  • 在某些Unix和Linux版本中,您执行mmap并且也可能打开/ dev / mem以获取非空指针,其逻辑地址非零但物理地址为零,它可能需要一些访问权限。
  • 我在Windows上不确定。

PS。其他答案似乎使语言级指针和物理地址混淆。

答案 1 :(得分:4)

  

在C / C ++中,不允许访问地址0。

是的,你可以,只要那里有可寻址的内存。在大多数平台上,不会有。

  

在什么情况下允许访问物理地址0?

如果映射到虚拟内存,您可以访问任何物理地址。如果那里有任何敏感,那么操作系统可能不允许在用户代码中使用它。在内核中,只是设置页表以包含该地址。

答案 2 :(得分:3)

通常,address space中的virtual memoryoperating system管理。

独立的C(或C ++)实现当然可以允许您以实现特定的方式取消引用(void*)0。但要注意undefined behavior

C和C ++标准对NULL指针非常小心(并且C ++ 11添加了nullptr关键字有几个原因。)

允许C编译器(至少是托管实现)在成功解除引用后,指针不为空。 GCC中的一些优化就是这样做的。

大多数托管的C或C ++实现都有一个空指针,这是一个全零位的字,但标准不需要这样做(但是,它很常见;它有助于编译器和libc)。 然而,实际上,许多软件假设NULL由全零位表示(理论上这是一个错误)。

我知道没有C实现NULL不是全零位,但这不是必需的。但是,编写这样的编译器会很头疼。

在某些操作系统上,应用程序可以更改其地址空间,例如在mmap(2)或Linux上使用POSIX

如果你真的想要,你可以在C中访问地址0,但你真的不应该这样做。

答案 3 :(得分:3)

C或C ++中没有规范允许您为指针分配特定的物理地址。所以你的问题是关于"如何访问地址0"可以转换为"如何将0地址分配给指针"正式没有答案。您无法在C / C ++中为指针分配特定地址。

但是你可以通过整数到指针的转换来获得这种效果: -

uintptr_t null_address = 0;
void *ptr = (void *) null_address;

答案 4 :(得分:1)

C标准不要求平台提供对任何特定物理内存位置的访问,零或其他。虽然在(char *)0x1234的许多嵌入式平台上访问物理位置​​0x1234很常见,但C标准中没有任何内容要求。

如果尝试访问空指针,C标准也不要求平台特别做任何事情。因此,如果编译器编写者想要将空指针取消引用视为对物理位置零的访问,则此类行为将符合。

对地址为零的访问有意义且有用的编译器通常将空指针访问解释为对位置零的访问。唯一的问题是对于位置零访问有用的平台,但编译器编写者不知道。这种情况通常只能通过检查编译器的文档来处理,以便强制编译器像其他任何地址一样处理空指针。

答案 5 :(得分:0)

你的问题有点令人困惑。你问是否可以访问物理地址零。"在现代分页操作系统中,应用程序根本无法指定物理地址。物理地址只能通过内核模式访问。

在虚拟内存系统中,通常不将虚拟内存的第一页映射到进程地址空间。因此,访问虚拟地址零将触发访问冲突。

在这样的系统中,应用程序通常可以通过系统服务将第一页映射到进程访问空间。即使页面默认不存在,也可以由应用程序添加。

答案是可以在内核模式下访问物理内存地址为零,并且如果应用程序将该页面映射到内存(并且操作系统允许),则可以访问虚拟地址零。