我记得Scott Meyers教会我
func(shared_ptr(new P), shared_ptr(new Q));
很危险,因为(如果我没记错的话)内存分配的顺序,引用计数(构建)和的赋值>函数参数 允许leak (理论上?)在极少数情况下出现。为防止这种情况,应将shared_ptr
封装在函数调用中,例如在make_shared()
。
func(make_shared<P>(), make_shared<Q>());
以下是关于它的一些discussion。
我想知道某些系统中是否存在(当前)编译器 ,在某些错误情况下确实可能会留下一些漏洞?或者那些时代已经消失,还是只是理论上的呢?
最有趣的是,如果其中任何一个都有这个问题:
有没有人在他的特定平台上观察到这种行为?
答案 0 :(得分:4)
这不是平台问题,而是一个例外安全问题。因此,您实际问题的答案是:所有这些平台可能会出现问题。
由于两件事情而引起内存泄漏问题:
new
分配内存可能会抛出bad_alloc
boost::shared_ptr
的文档可以很好地捕获here
对一般问题here (GOTW)
进行了更详细的处理它可能是“罕见”的原因是因为获取bad_alloc
真的不常见,但是如果要避免内存泄漏,你的代码必须安全地处理这种可能性。
(我说“可能”展示它 - 如果bad_alloc
失败,我还没有检查过它们都会抛出new
...)
答案 1 :(得分:0)
因为两个new
操作都将首先完成,然后它们被传递到shared_ptr
的构造函数中,但是shared_ptr
构造首先是未指定的,所以新创建的对象之一可能会导致内存泄漏。
答案 2 :(得分:0)
func(shared_ptr(new P), shared_ptr(new Q));
C ++编译器可以按以下顺序自由实现:
(编译器可以按任意顺序执行1,2,3和4,只要1在4之前,2在3之前)。
按照上面的顺序,如果P
的构造函数或对new
的调用抛出,Q
是内存泄漏(内存已分配,但shared_ptr
不是然而围绕它建造。)
因此,您应该调用std::make_shared
(它可以优雅地处理分配的异常),并且您知道当std::make_shared
为其中一个返回shared_ptr
时,{{1}}已完全构造,不会泄漏。
我想知道现场是否有(当前)编译器,某些系统确实可能在某些错误情况下留下一些漏洞?
所有符合标准的编译器都会有此行为。
答案 3 :(得分:0)
如果优化程序执行以下优化A;B;A;B => A;A;B;B
,则在具有重新排序优化程序的任何平台上都不安全。这种优化提高了代码缓存效率,所以一般来说这是一个好主意。
显然,如果未指定相对顺序,优化器只能重新排列B和A,这恰好就是这种情况。