2

假设我们有以下代码片段

int* p = new int[5];

我们的代码在保护模式下运行。因此,位于我们p变量中的地址不是物理地址,而只是为我们的应用程序分配的部分虚拟内存的地址。当然,我们的系统还受到保护,免受内存违规尝试的影响。

在这些情况下,是否有可能给我们一个“零”地址,这样我们就会有p = 0并且它是正确的?当然,我考虑到 value0被视为 a nullptr,所以如果这个地址是正确的,它可能会产生误导。

事实上,是否有任何规则告诉我们什么是合法的可寻址范围?

当然,没有给出这个值还有另一个原因,但我不知道我是否正确 - 在 C (C++) 中,零值的指针被以特殊方式处理,所以如果我们的指针会注意到差异指向分配的内存,或者它的值为零,因为它是nullptr

4

4 回答 4

3

是否可以给定一个“零”地址,这样我们就有 p = 0 并且它是正确的?

我认为您正在混淆虚拟内存管理的物理和逻辑方面。

在逻辑方面,保证您的程序永远不会看到比较等于零的指针:

6.3.2.3 (3) 定义整数常量表达式 0 和这样的表达式转换为 (void *) 作为null指针常量。如果将空指针常量转换为指针类型,则生成的指针(称为空指针)保证与指向任何对象或函数的指针不相等。

但是,在物理方面,没有这样的限制:没有什么可以阻止虚拟内存管理系统为您的程序提供物理地址为零的内存块。但是,该物理地址永远不会出现在与指针常量零值匹配的虚拟地址处:物理地址被虚拟内存管理系统对您的程序隐藏,并且保证与指针常量零对应的虚拟地址不会由编译器分配给您的程序。

于 2013-10-28T17:32:38.340 回答
2

常量“0”表示空指针。不过,这不一定存储为指针中的文字值 0x00000000。因此,理论上您可以将 0x00000000 作为对象的地址返回,如果将常量 0 存储到将空指针存储为不同值的指针中,这将是有效的。

实际上,这在我所知道的任何编译器中都不会发生。

于 2013-10-28T17:10:30.353 回答
1

为基于 C 的程序提供虚拟内存的运行时环境通常不允许0x00000000(或附近的任何东西)成为有效地址。

您将不得不努力使指针具有0x00000000值并且仍然有效!通常,这意味着手动进行 OS 系统调用以映射虚拟内存 ( mmap, VirtualAlloc)。在某些情况下,操作系统具有防止映射该特定内存页面的保护措施。例如,在某些旧版本的 Windows 中,您必须1作为要映射的地址而不是0. 在某些版本的 Linux 上,您必须先设置mmap_min_addr0才能映射该页面。

于 2013-10-28T17:15:09.137 回答
0

是的,实际上我的部分问题是“您是否可以相信 p==0 意味着分配失败?”。

默认情况下,new如果分配失败以发出错误信号,则会引发异常,因此检查返回值是没有意义的。如果你使用 new 的 no-throw 版本,那么你保证返回的值不会是nullptr,所以测试会很好。

现在,关于使用返回的内存是否安全的更大问题,它可能会也可能不会。不同的操作系统实现会过度使用内存,因此它们会为应用程序授予比物理可用内存更多的内存,假设当应用程序可能需要它时,可能会在其他地方释放一些东西。考虑到这一点,请注意,如果您要求大量内存,即使它是由语言构造 ( new) 和操作系统(下面的分配器实现)分配给您的,也不能保证您将能够用它。

于 2013-10-28T18:41:10.887 回答