我真的不敢相信我找不到明确的答案......
在使用new运算符初始化C++类构造函数抛出异常后,如何释放分配的内存.例如:
class Blah
{
public:
Blah()
{
throw "oops";
}
};
void main()
{
Blah* b = NULL;
try
{
b = new Blah();
}
catch (...)
{
// What now?
}
}
Run Code Online (Sandbox Code Playgroud)
当我尝试这个时,b在catch块中是NULL(这是有道理的).
在调试时,我注意到conrol在它到达构造函数之前进入了内存分配例程.
这在MSDN网站上似乎证实了这一点:
当new用于为C++类对象分配内存时,在分配内存后调用对象的构造函数.
因此,请记住,b永远不会分配局部变量(即在catch块中为NULL),如何删除分配的内存?
得到一个跨平台的答案也很好.即,C++规范说什么?
澄清:我不是在讨论类在c'tor中分配内存然后抛出的情况.我很欣赏在这种情况下,不会召唤人.我在谈论用于分配THE对象的内存(Blah在我的例子中).
对象构造函数做多少工作是合理的?它应该只是初始化字段而不是实际对数据执行任何操作,还是可以让它执行某些分析?
背景: 我正在编写一个类,负责解析HTML页面并根据解析的信息返回各种信息.类的设计使得类的构造函数执行解析,如果发生错误则抛出异常.初始化实例后,解析后的值无需通过访问器进行进一步处理即可使用.就像是:
public class Parser {
public Parser(final String html) throws ParsingException {
/* Parsing logic that sets private fields */
/* that throws an error if something is erroneous.*/
}
public int getNumOfWhatevers() { return private field; }
public String getOtherValue() { return other private field; }
}
Run Code Online (Sandbox Code Playgroud)
在设计课程后,我开始怀疑这是否是正确的OO练习.解析代码是否应放在void parseHtml()方法中,并且一旦调用此方法,访问者只返回有效值?我觉得好像我的实现是正确的,但我不禁觉得有些OO纯粹主义者可能因为某种原因发现它不正确,并且以下的实现会更好:
public class Parser {
public Parser(final String html) {
/* Remember html for later parsing. */
}
public void parseHtml() throws ParsingException {
/* Parsing logic …Run Code Online (Sandbox Code Playgroud) 在以下代码中:
#include <memory>
#include <iostream>
void mydeallocator(int * x) {
std::cerr << "Freeing memory" << std::endl;
delete x;
}
struct Foo {
std::unique_ptr <int,std::function <void(int*)>> x;
Foo(bool fail) : x(new int(1),mydeallocator) {
if(fail)
throw std::runtime_error("We fail here");
}
};
int main() {
{auto foo1 = Foo(false);}
{auto foo2 = Foo(true);}
}
Run Code Online (Sandbox Code Playgroud)
看来,Foo(true)调用时内存没有被正确释放.也就是说,当我们编译并运行该程序时,我们得到了结果:
Freeing memory
terminate called after throwing an instance of 'std::runtime_error'
what(): We fail here
Aborted
Run Code Online (Sandbox Code Playgroud)
我相信该消息Freeing memory应该被调用两次.基本上,根据这个问题和这里和这里的ISO C++人员,我的理解是堆栈应该在构造函数上展开, …
我想问一个关于构造函数中的内存泄漏的问题.我们来考虑一个课程:
class Foo
{
public:
Foo(){ throw 500;}
};
Run Code Online (Sandbox Code Playgroud)
有什么区别
std::unique_ptr<Foo> l_ptr = std::make_unique<Foo>();
Run Code Online (Sandbox Code Playgroud)
和
std::unique_ptr<Foo> l_ptr;
l_ptr.reset(new Foo());
Run Code Online (Sandbox Code Playgroud)
在我看来,make_unique的解决方案应该保护我免受内存泄漏,但在这两种情况下我得到了相同的valgrind结果:
$ valgrind --leak-check=full ./a.out
==17611== Memcheck, a memory error detector
==17611== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==17611== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==17611== Command: ./a.out
==17611==
terminate called after throwing an instance of 'int'
==17611==
==17611== Process terminating with default action of signal 6 (SIGABRT)
==17611== at 0x5407418: raise …Run Code Online (Sandbox Code Playgroud) 假设有这样的代码:
class CFoo
{
public:
CFoo()
{
iBar = new CBar();
}
private:
CBar* iBar;
};
....
CFoo* foo = new CFoo();
Run Code Online (Sandbox Code Playgroud)
执行上面的行时,将分配第一个内存来保存CFoo对象.但是如果新的CBar()行引发异常(由于内存不足),系统会自动解除分配先前分配给CFoo对象的内存吗?我认为它必须,但找不到任何明确的参考说明.如果没有,编码器将如何释放内存,因为它不会被分配给foo?
感谢所有的回复.
我重新格式化了我的问题,以便在包含类的构造函数抛出异常之后理解成员指针的状态
我的示例类:)
class Foo
{
public:
Foo()
{
int error = 0;
p = new Fred;
throw error; // Force throw , trying to understand what will happen to p
}
~Foo()
{
if (p)
{
delete p;
p = 0;
}
}
private:
Fred* p;
};
int main()
{
try
{
Foo* lptr = new Foo;
}
catch (...)
{}
}
Run Code Online (Sandbox Code Playgroud)
类foo的consturctor会因某些随机原因而抛出异常.我知道foo的desturctor永远不会被调用,但在这种情况下,p的析构函数会被调用吗?
将p作为增强智能指针而不是指向fred的原始指针有什么不同.
谢谢.