巨大的内存分配:堆栈与堆

Huge memory allocation: stack vs heap

本文关键字:堆栈 分配 内存 巨大      更新时间:2023-10-16

>我做了一个需要1 GB内存的结构。当我在堆上分配它时,程序启动得很快,我在应用程序管理器中看到,它的内存使用量上升到那个数量,但是当我像一个简单的变量一样在堆栈上分配它时,应用程序需要更多时间来启动,在应用程序管理器上,我看到它没有使用那么多的内存(只有几千KB(。这是为什么呢?这是否意味着建议在堆中存储大量数据?这种情况更快吗?我知道通常由于映射等原因,在堆栈上分配内存会更快,但在这种情况下,这很奇怪。谁能解释一下? 提前感谢!

在典型的桌面系统上,堆栈的大小通常约为一到几兆字节。在嵌入式设备上可能更少。

如果分配的内存超过堆栈大小的内存,则操作系统通常会在您尝试访问内存时立即终止程序。

这是否意味着建议在堆中记录大量数据?

建议对大量数据使用免费存储(动态分配(,因为大量数据会溢出堆栈。

我看到应用程序管理器没有使用那么多的内存(只有几KB(。

通常,操作系统在访问进程时为该内存分配一页内存。由于您的程序没有因堆栈溢出而崩溃,我怀疑您从未访问过内存,因此没有为数据分配内存。

是的,建议动态进行大量分配 - 因为这样您就可以优雅地应对失败(术语的强制性说明(。

例如,这个:

void might_throw(size_t sz) {
std::vector<int> v(sz);
// ...
}

如果对于足够大的sz失败,将抛出std::bad_alloc,这意味着我可以选择捕获异常并使用较小的数字重试。即使我无法有效地恢复,堆栈展开也可以安全地清理我的其他对象。

相反

void will_just_die() {
int a[SomeEnormousConstant];
// ...
}

如果无法真正创建a则没有恢复机制。该程序只会崩溃,很难,没有堆栈展开或(标准(错误处理机制。

这可能会立即发生,也可能仅在您实际尝试访问比成功分配的更多的a时才会发生。如果你很不幸,它甚至可能看起来有效,但会破坏其他东西。


给定分配如何在外部显示的详细信息非常依赖于操作系统,我不确定您正在使用什么 - 应用程序管理器是OSX管理器吗?

直接映射大型动态分配是很常见的,在这种情况下,它会立即显示为虚拟大小的增加,但除了访问之外,可能仍然不会分配任何物理页面。

如果自动("堆栈"(分配只是执行帧指针算术,并再次依赖于物理页面的延迟分配,这不会影响虚拟或物理大小(同样,直到您尝试实际访问该内存(。

我不知道为什么自动版本需要更长的时间才能启动 - 您必须提供一个实际上可重现的 MCVE,以及您的操作系统/平台详细信息才能获得答案。