class someclass {};
class base
{
int a;
int *pint;
someclass objsomeclass;
someclass* psomeclass;
public:
base()
{
objsomeclass = someclass();
psomeclass = new someclass();
pint = new int();
throw "constructor failed";
a = 43;
}
}
int main()
{
base temp();
}
在上面的代码中,构造函数抛出。哪些对象将被泄漏,如何避免内存泄漏?
int main()
{
base *temp = new base();
}
上面的代码怎么样?在构造函数抛出后,如何避免内存泄漏?
发布于 2012-01-28 20:32:14
我认为顶部的答案是错误的,并且仍然会泄漏内存。如果类成员的析构函数抛出异常(因为它从未完成初始化,并且可能某些成员从未到达其构造函数调用),则不会调用该类成员的析构函数。它们的析构函数仅在类的析构函数调用期间调用。
这个简单的程序演示了这一点。
#include <stdio.h>
class A
{
int x;
public:
A(int x) : x(x) { printf("A constructor [%d]\n", x); }
~A() { printf("A destructor [%d]\n", x); }
};
class B
{
A a1;
A a2;
public:
B()
: a1(3),
a2(5)
{
printf("B constructor\n");
throw "failed";
}
~B() { printf("B destructor\n"); }
};
int main()
{
B b;
return 0;
}
输出如下(使用g++ 4.5.2):
A constructor [3]
A constructor [5]
B constructor
terminate called after throwing an instance of 'char const*'
Aborted
#include <stdio.h>
class A
{
int x;
public:
A(int x) : x(x) { printf("A constructor [%d]\n", x); }
~A() { printf("A destructor [%d]\n", x); }
};
class B
{
A * a1;
A * a2;
public:
B()
try // <--- Notice this change
: a1(NULL),
a2(NULL)
{
printf("B constructor\n");
a1 = new A(3);
throw "fail";
a2 = new A(5);
}
catch ( ... ) { // <--- Notice this change
printf("B Cleanup\n");
delete a2; // It's ok if it's NULL.
delete a1; // It's ok if it's NULL.
}
~B() { printf("B destructor\n"); }
};
int main()
{
B b;
return 0;
}
如果您运行它,您将得到预期的输出,其中只有分配的对象被销毁和释放。
B constructor
A constructor [3]
B Cleanup
A destructor [3]
terminate called after throwing an instance of 'char const*'
Aborted
class C
{
std::shared_ptr<someclass> a1;
std::shared_ptr<someclass> a2;
public:
C()
{
std::shared_ptr<someclass> new_a1(new someclass());
std::shared_ptr<someclass> new_a2(new someclass());
// You will reach here only if both allocations succeeded. Exception will free them both since they were allocated as automatic variables on the stack.
a1 = new_a1;
a2 = new_a2;
}
}
发布于 2008-09-29 05:01:20
是的,该代码会泄漏内存。使用"new“分配的内存块在引发异常时不会被释放。这是RAII背后的部分动机。
要避免内存泄漏,请尝试如下所示:
psomeclass = NULL;
pint = NULL;
/* So on for any pointers you allocate */
try {
objsomeclass = someclass();
psomeclass = new someclass();
pint = new int();
throw "constructor failed";
a = 43;
}
catch (...)
{
delete psomeclass;
delete pint;
throw;
}
发布于 2008-09-29 05:02:39
如果你抛出了一个构造函数,你应该清理掉在调用抛出之前的所有东西。如果你正在使用继承或者抛出一个析构函数,你真的不应该这样做。这种行为很奇怪(没有我的标准,但它可能是未定义的?)。
https://stackoverflow.com/questions/147572
复制相似问题