在析构函数中调用“delete”运算符时出现编译器错误“编译器堆空间不足”
Posted
技术标签:
【中文标题】在析构函数中调用“delete”运算符时出现编译器错误“编译器堆空间不足”【英文标题】:Compiler error "compiler is out of heap space" when calling `delete` operator in the destructor 【发布时间】:2018-06-29 14:40:46 【问题描述】:我写了一个名为“TreeContainer”的类。我的目标是设计一个树容器,将内容保存在树状层次结构中。每个树容器都应该像文件系统中的文件夹/目录一样工作。一个文件夹(树)可以有子文件夹(子树)和其他文件(子项)。
我将它包含在另一个源文件中,说它的名称是“TreeUser.cpp”。当我尝试调试/运行我的项目时,Visual Studio 会一一编译项目源文件,我会在 IDE 的“输出”面板中查看当前正在编译的文件。当涉及到 TreeUser.cpp 文件时,它花费了太多时间。最后给出下面的致命错误,编译停止。
错误 C1060 编译器堆空间不足 [此处为项目名称] [Visual Studio 安装路径]\visual studio\vc\tools\msvc\14.14.26428\include\xmemory0 962
类的代码如下。
TreeContainer.cpp
#pragma once
#include <vector>
template <class T>
class TreeContainer
public:
using SubTreeContainerType = std::vector<TreeContainer<T *> *>;
using SubItemContainerType = std::vector<T *>;
TreeContainer();
~TreeContainer();
// ... (Lots of member functions here. Removing or keeping them has no effect.)
private:
SubTreeContainerType SubTrees;
SubItemContainerType SubItems;
;
template <class T>
TreeContainer<T>::TreeContainer()
: SubTrees(), SubItems()
template <class T>
TreeContainer<T>::~TreeContainer()
for (typename SubTreeContainerType::iterator it=SubTrees.begin(); it!=SubTrees.end(); ++it)
//delete *it; (I get the error when I uncomment this line.)
for (typename SubItemContainerType::iterator it=SubItems.begin(); it!=SubItems.end(); ++it)
delete *it;
经过多次试验,我发现析构函数中的行导致了问题。删除它可以解决问题。但我需要那条线来清理内存。
在该行中,我在容器SubTrees
的内容上调用delete
运算符。它应该递归地调用每个子树上的析构函数。我在这里做错了什么还是这是 Visual Studio 中的错误。
IDE 版本:Visual Studio Community 2017 15.7.4
命令行选项:
/permissive- /GS /W3 /wd"4290" /wd"5040" /Zc:wchar_t /ZI /Gm- /Od /sdl /Fd"x64\Debug\vc141.pdb" /Zc:inline /fp :precise /D "SC_DEBUG" /D "_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /MDd /std:c++17 /FC /Fa "x64\Debug\" /EHsc /nologo /Fo"x64\Debug\" /Fp"x64\Debug\Project Name.pch" /diagnostics:classic
【问题讨论】:
如果这些容器是用来拥有相关对象的,那么您真的应该使用std::unique_ptr<T>
,而不是T*
。这样至少,你不需要为这个对象滚动你自己的析构函数。即使std::unique_ptr
不适合您的任务,您仍然应该重组代码以遵守适当的 RAII 约定,而不是让单个对象直接负责多个资源的生命周期,并且而是将每个资源的职责委托给它自己的对象。
【参考方案1】:
看起来您从模板创建了无限多个类,因为TreeContainer<T>
中的SubTreeContainerType
引用了TreeContainer<T *>
(T
指针的容器)。
而析构函数需要子树向量的析构函数,子树又需要TreeContainer<T *>
的析构函数,又需要TreeContainer<T **>
的析构函数等pp。
解决方案:
using SubTreeContainerType = std::vector<TreeContainer<T> *>;
或者,如果您真的希望子树容器引用指向 T
的指针,请在实现方法之前为中断递归的指针添加模板特化。
【讨论】:
以上是关于在析构函数中调用“delete”运算符时出现编译器错误“编译器堆空间不足”的主要内容,如果未能解决你的问题,请参考以下文章
如果debug调试的时候中断总是停在析构函数的delete[] p上
即使内存不是动态分配的,在析构函数中是不是需要`delete ptr;`? [复制]