当超过可能的虚拟地址数时会发生什么情况

What happens when the number of possible virtual addresses are exceeded

本文关键字:什么情况 虚拟地址      更新时间:2023-10-16

>假设我正在为一个虚拟空间地址(4294967296地址)有 32 位的环境编写一个程序,如果创建超过 4294967296 个变量,有效地超过可能地址的数量,会发生什么?还是环境中的所有程序都共同使用超过4294967296地址?

这完全取决于您尝试如何做到这一点。它可能会崩溃,可能会返回错误,可能会引发异常。

如果创建超过 4294967296 个变量会发生什么

我猜你很困惑。你不会创建那么多变量。你实际上使用C动态内存分配(使用malloc&free和friends)或C++动态内存分配(例如动态内存管理,高于低级内存管理,如::operator new,在许多实现中使用的是malloc)。

请注意,malloc(在 C 中)和new(在 C++ 中)不会创建新变量。他们正在分配新的内存区域,如果你用 C 语言编码int *ptr = malloc(100000*sizeof(int);,或者用 C++int* ptr = new int[100000];编码,它们的地址可以进入一个指针变量......

变量(在 C 或 C++ 中)是一个源代码的东西,它有一个名称(例如ptrx000002array在此答案中)和范围。在执行过程中,只有位置很重要(变量不存在)。阅读有关内存地址的信息(实际位置是什么)。

因此,要拥有许多变量,您需要拥有一个巨大的源文件,例如:

int x000001;
int x000002;

等等。您可能可以(使用其他程序)生成如此巨大的 C 或C++源文件,例如:

////etc
int x999998;
int x999999;

但即使你生成了 40 亿行的源 C 文件,你也不会有耐心编译它。如果你这样做了,编译肯定会失败(至少在链接时,我认为这是你程序整体编译的一部分)。

请注意,数组声明只定义一个变量:

/// one single variable, but a huge one
int array[4294967296];

声明一个名为array的变量。同样,这不会编译和链接(如果变量是某个函数中的局部变量,则至少会在运行时获得堆栈溢出)。典型的调用堆栈限制为一兆字节或几兆字节(这取决于操作系统和计算机)。

查看虚拟地址空间维基页面中的图片,了解指针别名的含义以及虚拟内存是什么。

实际上,在 32 位计算机上,给定进程的虚拟地址空间通常限制为 3GB(每个进程正在运行一些可执行文件并具有自己的虚拟地址空间)。详细信息特定于操作系统。在 Linux 上,使用 setrlimit(2) - 可能通过 bash shell 的内置ulimit- 来降低这个限制。

在 Linux 上,动态内存分配(mallocnew)是基于修改虚拟地址空间的系统调用,特别是 mmap(2)。此类调用可能会失败(然后malloc会通过返回NULL而失败,new会引发异常),并且在 32 位系统上,它们将在 3GB 之前失败。您可能希望禁用内存过度使用。

如果你碰巧使用 Linux 系统, 阅读 proc(5) 并尝试

cat /proc/self/maps
cat /proc/$$/maps

然后了解他们的输出是什么。您可能还应该阅读高级 Linux 编程。

我建议花几天时间阅读: 操作系统 :三个简单的部分(可免费下载)。

(在Windows或MacOSX或Android上,mallocnew也使用一些操作系统原语来增加虚拟地址空间。我让你找到哪些)

如果特定进程尝试超过进程虚拟地址空间的大小,则只会耗尽内存。将要发生的事情正是进程耗尽内存时通常发生的情况 - 内存分配函数将返回空指针或类似的东西。此外,从理论上讲,在启用交换的基于虚拟内存的操作系统中,地址空间不足是"内存不足">的唯一方法(现实生活比这要复杂一些,但总的来说确实如此)。

至于系统上的所有进程。你的问题被误导了。操作系统,即使它是 32 位操作系统,也不以任何方式限制为所有进程的单个 32 位地址空间。对于所有实际手段和目的,操作系统可以为不同的进程维护几乎不受限制数量的同时独立 32 位地址空间。

如果在一个块中创建具有静态存储持续时间的变量或自动变量,编译器或链接器可能无法创建可执行文件。

如果在多个函数中创建许多自动变量,并导致所有变量同时处于活动状态,则程序将因堆栈溢出而崩溃。

如果尝试从动态存储分配这么多字节,分配将失败。

达到限制时,提交内存的虚拟分配将失败。这意味着即使是标准的 32 位进程也可能会出现虚拟内存分配失败。 也许该链接可以帮助您: 突破 Windows 的极限:虚拟内存

相关文章: