据GOTW #56,有下面的代码中潜在的经典内存泄漏和异常的安全问题:如何解决这个典型的异常不安全代码?
// In some header file:
void f(T1*, T2*);
// In some implementation file:
f(new T1, new T2);
的原因是,当我们new T1
,或new T2
,有可能是例外从班构造抛出。
同时,根据该解释:
简要回顾一下:如“新T1”的表达式称为,只需足够的,一个新 表达。回顾一下新的表达确实(我会忽略简单 布局和排列形式,因为他们不是很 与此有关):
分配内存
它构造了一个在存储新对象
如果因为异常的分配的内存被释放的构造失败
因此,每个新的表达基本上是一个系列的两个函数调用:) 一个调用操作者新的((无论是全球性的,或一个由 正在创建的对象的类型提供),然后到一个呼叫 构造函数。
对于实施例1,可以考虑如果编译器决定 如下生成代码时会发生什么:
1:T1
分配内存 2:构建T1
3:T2
4分配内存:构造T2
5:调用f()的问题是这样的:如果任一步骤3或步骤4中失败,因为一个 异常,C++标准并不要求的T1对象是 被销毁并且其内存释放。这是一个经典的内存泄漏, 和显然不是一件好事。 [...]
通过阅读更多:
为什么不标准只是防止这个问题通过要求编译器做正确的事情,当它来清理?
最基本的答案是,它没有注意到,甚至现在,它已经注意到它可能是不希望解决它。 C++标准允许编译一些宽容度表现的评价的顺序,因为这允许进行优化,可能否则是不可能的编译器。要允许此,表达评价规则的方式,是不是异常安全规定,所以如果你想写你需要了解和避免这些情况的异常安全的代码。 (请参阅下面的最佳做法。)
所以我的问题是:
如何解决这个典型的异常不安全的代码?我们应该避免编写这样的代码吗?
答案弄得我一点点,为了处理 构造失败,我们应根据C++ FAQ抛出从构造异常,并分配都被正确释放一定的内存,所以假设T类没有实现代码处理建设失败,我们在上面的代码中是否还有异常安全问题?
谢谢你的时间和帮助。
*如何解决这个典型的异常不安全的代码?我们应该简单地避免编写这样的代码吗? - 这篇文章(写在2009年,顺便说) - “在您穿过公司代码档案的尘土飞扬的角落时,您会发现以下代码片段......”。简单地说 - 你不应该写这样的代码。 – SChepurin