在堆上创建静态数组?
我需要创建一个非常大的数组。假设 50 兆字节。
我可以安全地将其创建为普通的静态数组吗?编译器会将其放在堆栈上(可能会导致堆栈溢出),还是会足够聪明地将其放在堆上?
如果没有办法这样做,是否有一种简单的方法可以在程序启动时使用 malloc 或“new”来实现,但在程序结束时自动释放它?
I need to create a very large array. Let us say 50 megabytes.
Can I be safe to create it as a normal static array? Will the compiler put it on the stack (possibly causing a stack overflow), or will it be smart enough to put it on the heap?
If there is no way to do so, is there an easy way to do it with malloc or "new" when program starts, but automatically free it when program ends?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
据我了解,静态变量并不存在于堆栈中。如果他们这样做了,当你弹出他们所在的堆栈帧时他们会去哪里?静态函数变量需要在调用之间保持其状态,因此从逻辑上讲,静态数据应该保存在堆上。
此外,当程序结束时,所有内容都会自动释放。
As I understand it, static variables don't live on the stack. If they did, where would they go when you pop the stack frame they live in? Static function variables need to keep their state between calls, so logically, the static data should be kept on the heap.
Also, when the program ends, everything is automatically deallocated.
执行此操作的简单方法是使用 std::vector
或潜在的 std::deque (取决于您的使用情况)。
堆栈溢出是指理论堆栈和理论堆冲突并混合的情况。如果堆栈溢出,那么堆也会失败。
某些系统具有堆栈帧的最大大小(这是特定于编译器和平台的),有关详细信息,请参阅编译器文档。因此,通常最好动态分配巨大的结构(尽管不是直接分配)。
std::vector 可以做到这一点(可能)。它有一个小的本地对象存在,但主要有效负载(通常)是作为动态堆分配实现的。
The easy way to do this is by using std::vector
or potentially std::deque (depending on your usage).
A stack overflow is when the theoretical stack and theoretical heap collide and intermingle. If the stack was going to overfow then the heap is also going to fail.
Some systems have a maximum size of stackframe (this is compiler and platform specific) see your compiler documentation for details. As a result it is usually better to allocate huge structures dynamically (though not directly).
std::vector does this (probably). It has a small local object presence but the main payload (usually) is implemented as a dynamic heap allocation.
根据我的经验,最好在堆上分配这么大的数组(因此通过 new ) - 我在堆栈上分配 2 MB 后在 unix 系统上看到了程序核心转储...
如果您想要自动删除,可以使用智能指针(例如 boost::scoped_array)。但是,既然您提到“程序结束时自动删除它”,您实际上不必执行任何操作 - 操作系统将在进程终止时回收所有进程的内存。
不管怎样,你确实应该使用 std::vector 而不是原始数组。
It's better, in my experience, to allocate such a large array on the heap (thus via new) - I have seen a program core dump on a unix system after allocating 2 MB on the stack...
If you want automatic deletion, you could use a smart pointer (say, boost::scoped_array). But, since you mention "deleting it automatically when the program ends", you actually don't have to do anything - the operating system will reclaim all of your process's memory when it terminates.
Anyway, you really should use std::vector instead of a raw array.
以今天的标准来看,50 兆字节并不算太多。
您可以使用 C++ new 运算符在程序开始处分配它,并在末尾(或在定义的程序部分的开始/结束处)使用 delete[] 取消分配它。
如果这个数组代表例如要加载的某个文件,那么当然最好在文件加载到内存中时分配它。最佳情况下,您只能将文件的一部分映射到内存中(例如:1MB、2MB 或您要使用的其他逻辑“单元”)(请参阅 Windows 中的 MapViewOfFile 和 UNIX 系统中的 mmap)。这样您就可以加载非常大的文件,而不会耗尽虚拟内存。
50 megabytes is not too much by today standards.
You can allocate it at the start of your program using C++ new operator, and deallocate it with delete[] at end (or at the start/end of a defined program section).
If this array represents e.g some file to be loaded, it's better to allocate it of course when the file is loaded into memory. Optimally, you can only map only a section of the file into memory (e.g: 1MB, 2MB, or another logical "unit" you want to use) (see MapViewOfFile in Windows and mmap in UNIX systems). This way you can load very large files without exhausting your virtual memory.
如果您静态分配它,它将被静态分配。在典型情况下,可执行文件中会有某种记录,指定特定变量应该是大小为 N 的零初始化块。加载程序通常会遵循这一点,就像它为程序代码分配空间一样这样(例如,它会分配地址空间,但通常不是实际内存来支持它,直到/除非您实际读取/写入该内存)。
If you allocate it statically, it'll be allocated statically. In a typical case, there will be a record of some sort in the executable that specifies that a particular variable should be a zero-initialized block of size N. The loader will normally honor that, just like it allocates space for the program's code and such (e.g., it'll allocate address space but quite often not actual memory to back it until/unless you actually read/write that memory).