以下是我的示例代码:
void test()
{
Object1 *obj = new Object1();
.
.
.
delete obj;
}
我在Visual Studio中运行它,它在'delete obj;'的行中崩溃了。 这不是释放与对象关联的内存的正常方法吗? 我意识到它会自动调用析构函数......这是正常的吗?
以下是代码段:
if(node->isleaf())
{
vector<string> vec = node->L;
vec.push_back(node->code);
sort(vec.begin(), vec.end());
Mesh* msh = loadLeaves(vec, node->code);
Simplification smp(msh);
smp.simplifyErrorBased(errorThreshold);
int meshFaceCount = msh->faces.size();
saveLeaves(vec, msh);
delete msh;
}
loadleaves()
是一个从磁盘读取网格并创建Mesh
对象并返回它的函数。(考虑vec
和node->code
只是关于文件的信息待开)
我应该删除delete msh;
行吗?
答案 0 :(得分:37)
这不是释放与对象关联的内存的正常方法吗?
这是管理动态分配内存的常用方法,但这不是一个好方法。这种代码很脆弱,因为它不是异常安全的:如果在创建对象和删除对象之间抛出异常,则会泄漏该对象。
使用智能指针容器会更好,您可以使用它来获取范围限制资源管理(通常称为resource acquisition is initialization或RAII)。
作为自动资源管理的一个例子:
void test()
{
std::auto_ptr<Object1> obj1(new Object1);
} // The object is automatically deleted when the scope ends.
根据您的使用情况,auto_ptr
可能无法提供您需要的语义。在这种情况下,您可以考虑使用shared_ptr
。
至于删除对象时程序崩溃的原因,您没有给出足够的代码,任何人都无法确定地回答该问题。
答案 1 :(得分:7)
您的代码确实使用常规方法来创建和删除动态对象。是的,完全正常(并且确实由语言标准保证!)delete
将调用对象的析构函数,就像new
必须调用构造函数一样。
如果你没有直接实例化Object1
但是它的某些子类,我会提醒你,任何要继承的类都必须有一个虚拟析构函数(这样才能正确)子类的析构函数可以在类似于这个的情况下调用 - 但是如果你的示例代码确实代表了你的实际代码,那么这不是你当前的问题 - 必须是别的东西,可能在你没有显示的析构函数代码中我们,或者您在该函数中未显示的代码中的某些堆损坏或它所调用的那些......?
auto
,作为所述函数的默认变量!
答案 2 :(得分:3)
答案 3 :(得分:2)
如果它在delete
行崩溃,那么你几乎肯定会以某种方式破坏堆。我们需要查看更多代码来诊断问题,因为您提供的示例没有错误。
也许你的堆上有一个缓冲区溢出,它破坏了堆结构,甚至像“双重自由”这样简单(或者在c ++情况下“双重删除”)。
另外,正如The Fuzz所指出的那样,你的析构函数也可能出错。
是的,delete
调用析构函数是完全正常和预期的,这实际上是它的两个目的之一(调用析构函数然后释放内存)。
答案 4 :(得分:2)
saveLeaves(vec,msh);
我假设接受msh
指针并将其放在vec
内。由于msh
只是指向内存的指针,如果删除它,它也会在向量内被删除。
答案 5 :(得分:1)
只是詹姆斯回答的更新。
这不是释放与对象关联的内存的正常方法吗?
是的。这是释放内存的正常方法。但是new / delete运算符始终会导致内存泄漏问题。
由于c ++ 17已经删除了auto_ptr auto_ptr。我建议使用shared_ptr或unique_ptr处理内存问题。
void test()
{
std::shared_ptr<Object1> obj1(new Object1);
} // The object is automatically deleted when the scope ends or reference counting reduces to 0.