当超过可能的虚拟地址数时会发生什么情况
What happens when the number of possible virtual addresses are exceeded
>假设我正在为一个虚拟空间地址(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++ 中)是一个源代码的东西,它有一个名称(例如ptr
或x000002
或array
在此答案中)和范围。在执行过程中,只有位置很重要(变量不存在)。阅读有关内存地址的信息(实际位置是什么)。
因此,要拥有许多变量,您需要拥有一个巨大的源文件,例如:
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 上,动态内存分配(malloc
或new
)是基于修改虚拟地址空间的系统调用,特别是 mmap(2)。此类调用可能会失败(然后malloc
会通过返回NULL
而失败,new
会引发异常),并且在 32 位系统上,它们将在 3GB 之前失败。您可能希望禁用内存过度使用。
如果你碰巧使用 Linux 系统, 阅读 proc(5) 并尝试
cat /proc/self/maps
cat /proc/$$/maps
然后了解他们的输出是什么。您可能还应该阅读高级 Linux 编程。
我建议花几天时间阅读: 操作系统 :三个简单的部分(可免费下载)。
(在Windows或MacOSX或Android上,malloc
和new
也使用一些操作系统原语来增加虚拟地址空间。我让你找到哪些)
如果特定进程尝试超过进程虚拟地址空间的大小,则只会耗尽内存。将要发生的事情正是进程耗尽内存时通常发生的情况 - 内存分配函数将返回空指针或类似的东西。此外,从理论上讲,在启用交换的基于虚拟内存的操作系统中,地址空间不足是"内存不足">的唯一方法(现实生活比这要复杂一些,但总的来说确实如此)。
至于系统上的所有进程。你的问题被误导了。操作系统,即使它是 32 位操作系统,也不以任何方式限制为所有进程的单个 32 位地址空间。对于所有实际手段和目的,操作系统可以为不同的进程维护几乎不受限制数量的同时独立 32 位地址空间。
如果在一个块中创建具有静态存储持续时间的变量或自动变量,编译器或链接器可能无法创建可执行文件。
如果在多个函数中创建许多自动变量,并导致所有变量同时处于活动状态,则程序将因堆栈溢出而崩溃。
如果尝试从动态存储分配这么多字节,分配将失败。
达到限制时,提交内存的虚拟分配将失败。这意味着即使是标准的 32 位进程也可能会出现虚拟内存分配失败。 也许该链接可以帮助您: 突破 Windows 的极限:虚拟内存
- 将指针分配给另一个指针时会发生什么情况?
- 在什么情况下,两个堆栈分配的结构对象的 this 点指向同一个地址?
- 在什么情况下,我想在 C/C++ 代码中使用内联汇编代码
- 发生注入类名时会发生什么情况?(C++)
- 在什么情况下,需要共享智能指针而无法使用唯一指针?
- 重新分配向量时,向量中的内存会发生什么情况
- 如果结构中的字符串比使用的 p/调用签名长或短,会发生什么情况?
- 为什么或在什么情况下,你会将参数作为C++中的引用(或指针)传递给函数?
- 如果我向一个12字节的缓冲区写入的字节数少于12,会发生什么情况
- 删除对象(具有不同类型)的引用时会发生什么情况?
- 如果我在 c++ 中以 new 的放置形式使用没有足够的内存,会发生什么情况?
- 使用 Google 基准测试时返回值会发生什么情况?
- 正在连接的等待条件变量的线程会发生什么情况?
- 如果未定义的C++行为符合 C 定义的行为,会发生什么情况?
- 在什么情况下,使用'const T*'输入参数比'const T&'更可取?
- 将虚拟方法定义为私有方法时会发生什么情况?
- 当超过可能的虚拟地址数时会发生什么情况
- 当声明了虚拟析构函数但没有实现时会发生什么情况
- 当运算符 new 返回此代码中的地址时会发生什么情况 "new T" ?
- 当异步回调调用虚拟函数,而基类构造函数尚未返回时,会发生什么情况