【问题标题】:Creating a static array on the heap?在堆上创建一个静态数组?
【发布时间】:2011-06-18 22:19:12
【问题描述】:

我需要创建一个非常大的数组。假设是 50 兆字节。

我可以安全地将它创建为普通的静态数组吗?编译器会将其放入堆栈(可能会导致堆栈溢出),还是会足够聪明地将其放入堆中?

如果没有办法这样做,有没有一种简单的方法可以在程序启动时使用 malloc 或“new”,但在程序结束时自动释放它?

【问题讨论】:

  • 您的意思是static 是关键字静态还是“非动态”?
  • 静态关键字。我认为这也意味着它不是动态的!

标签: c++ arrays static heap-memory stack-memory


【解决方案1】:

据我了解,静态变量并不存在于堆栈中。如果他们这样做了,当你弹出他们所在的堆栈帧时,他们会去哪里?静态函数变量需要在调用之间保持其状态,因此从逻辑上讲,静态数据应该保存在堆上。

另外,当程序结束时,所有的东西都会自动释放。

【讨论】:

  • 啊,我猜他们不会在堆栈上。
  • 所有东西都在堆栈上自动释放,而不是在堆上。
  • 它们不是都在为进程分配的内存中吗?一旦程序结束,它就会被释放回操作系统。
  • @Twisol:它们的内存将被释放,但不会调用元素的析构函数
  • @Twisol:不运行析构函数是一个重大决定:能够在那里执行一些统计信息、日志记录等非常好,并且一些对象可能使用共享内存、临时文件或其他资源不会自动释放(在他们的操作系统上)。此外,习惯性地删除内存可以更容易地发现 valgrind、purify、insure 等中的实际内存泄漏。
【解决方案2】:

执行此操作的简单方法是使用 std::vector

std::vector   data;
data.reserve(<Number of Elements);

或潜在的 std::deque(取决于您的使用情况)。

编译器会将其放入堆栈(可能会导致堆栈溢出),还是会足够聪明地将其放入堆中?

堆栈溢出是指理论堆栈和理论堆发生冲突和混合。如果堆栈会溢出,那么堆也会失败。

某些系统具有最大堆栈帧大小(这是特定于编译器和平台的),有关详细信息,请参阅编译器文档。因此,动态分配大型结构通常会更好(尽管不是直接分配)。

std::vector 这样做(可能)。它有一个小的本地对象存在,但主要有效负载(通常)是作为动态堆分配实现的。

【讨论】:

  • 我不想使用 std::vector。我想我可以利用析构函数并将其包装在一个类中。
  • 因为我问的是数组。
  • @Pepe:std::vector 在您想要执行的用法方面与 Array 有何不同?
  • @Charles:std::vector 拥有自己的类和动态分配的数组不会有什么开销?或者甚至只是一个普通的动态分配数组?
  • @Pepe:评论 +1 因为它让我崩溃了
【解决方案3】:

根据我的经验,在堆上分配这么大的数组(因此通过 new)会更好——在堆栈上分配 2 MB 后,我在 unix 系统上看到了程序核心转储...... 如果要自动删除,可以使用智能指针(例如 boost::scoped_array)。但是,由于您提到“程序结束时自动删除它”,您实际上不必做任何事情 - 操作系统会在它终止时回收您的所有进程的内存。

无论如何,你真的应该使用 std::vector 而不是原始数组。

【讨论】:

    【解决方案4】:

    如果您静态分配它,它将被静态分配。在典型情况下,可执行文件中会有某种记录,指定特定变量应该是大小为 N 的零初始化块。加载程序通常会尊重这一点,就像它为程序代码分配空间一样这样(例如,它会分配地址空间,但通常不是实际内存来支持它,直到/除非您实际读/写该内存)。

    【讨论】:

      【解决方案5】:

      按照今天的标准,50 兆字节并不算多。

      您可以使用 C++ new 运算符在程序开始时分配它,并在结束时(或在已定义程序部分的开始/结束处)使用 delete[] 解除分配。

      如果这个数组代表例如某个要加载的文件,当然最好在文件加载到内存时分配它。理想情况下,您只能将文件的一部分映射到内存中(例如:1MB、2MB 或您想要使用的其他逻辑“单位”)(请参阅 Windows 中的 MapViewOfFile 和 UNIX 系统中的 mmap)。这样您就可以在不耗尽虚拟内存的情况下加载非常大的文件。

      【讨论】:

      • 手动调用 newdelete 是 Leakapalooza 的门票。
      • 如果我不想要leakapalooza 的门票,那么我会在baby java 中编写代码!
      • @FredOverflow:如果您需要 C++ 2) .NET 或 Java 程序,您可以仔细跟踪资源 (RIAA)。
      猜你喜欢
      • 2014-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-12
      • 1970-01-01
      • 2018-02-26
      • 2016-07-03
      • 1970-01-01
      相关资源
      最近更新 更多