注意:这可能听起来很愚蠢。 我有一个使用原始指针的应用程序,并且应用程序中存在大量内存泄漏。
现在我的问题是用智能指针替换现有的原始指针是多么容易。 只是替换它们有助于减少由于不释放动态分配的内存而导致的内存泄漏。
为了进一步解释,这个应用程序是一个遗留应用程序,并且存在非常直接的内存泄漏,其中将分配内存并且不会在相同的函数本身中释放。
我使用DevPartner进行了内存分析,发现了许多方面。 Valgrind比Devpartner更好。
答案 0 :(得分:3)
使用智能指针肯定是清理应用程序的良好开端,但它们并非万能药。在一个设计良好的程序中,大量的内存泄漏可能只是粗心大意,但更有可能是您遇到了重大的设计问题,并且内存泄漏就是其中的一个症状。当您切换到智能指针时,您仍然需要进行设计选择,例如“谁拥有此对象”,“此对象的所有权是否在多个客户端之间共享”和“此对象的预期生命周期”以便选择针对给定方案的适当智能指针实现。但这将是一个很好的开始,因为为不同的情况选择适当的智能指针风格的过程将迫使你考虑这些事情,并可能会改善你的设计。
答案 1 :(得分:2)
毫无疑问,智能指针可以减轻程序员对内存所有权麻烦的负担。既然你没有提到这是遗留应用程序还是改变接口是多么容易(并不总是因为智能指针降级为原始指针而需要),我建议你在valgrind之类的工具上运行你的应用程序(在Linux上) )或净化(在Unices和Windows上)以跟踪内存泄漏。
根据我的经验,大多数内存泄漏都遵循某种模式(开发人员A错过了某些东西,开发人员B复制了该代码并随之解决了问题)。因此,在考虑使用智能指针之前,使用工具可以先解决内存泄漏问题。
如果您开始开发此应用程序 - 首先使用智能指针。它们将为您节省大量的时间和精力。
答案 2 :(得分:2)
我将“很可能”给这个公司。
一种形式的内存泄漏是指函数分配内存并且不会在函数的至少一个路径中删除它。某种范围的指针,如auto_ptr
,可能会很好地处理这个问题。 (注意:auto_ptr
是第一个ISO标准的一部分,并且在下一个标准中被弃用,因此很难给出使用什么作用域指针的建议。请参阅编译器和库文档以了解它们支持的内容。 )
另一种形式是分配对象,共享所有权,这意味着有多个例程使用它,并且没有简单的方法来判断每个人是否通过它。这是shared_ptr
的一个很好的候选人,但你必须要小心。在创建对象时分配给shared_ptr
,并确保使用的每个其他指针都是shared_ptr
。如果例程A,B和C通过shared_ptr
访问对象,并且您没有更改D,那么当例程A,B和C通过它时它就会消失,无论D的需要如何。< / p>
shared_ptr
要避免的一件事就是周期,因为如果我有一个shared_ptr
到J,J有一个shared_ptr
到K,而K有shared_ptr
即使从程序中的任何其他地方无法访问,也不会删除任何内容。你需要注意那些情况。您可以在循环中使用weak_ptr
分解它们,或者自己删除循环中的元素,或者只是使用泄漏。
要考虑的另一件事是将vector
和类似容器替换为动态分配的数组和其他动态分配的数据结构。这为您提供了大量免费的内存管理,尽管您仍然可以泄漏内存。如果向量变大,然后变小,则不会释放额外的内存。通常的做法,如果你真的需要回收记忆,那就是swap
带有自身副本的曾经大的矢量。
简而言之,有许多非常有用的工具可以实现大量内存管理的自动化,但它们并不能取代您的思维。只需将每个指针转换为shared_ptr
并将每个数组转换为vector
即可解决许多问题,但智能地使用这些问题会带来更大的好处。
答案 3 :(得分:1)
这取决于,如果对对象的硬引用阻止垃圾收集器释放它,垃圾收集程序仍然可能有内存泄漏。如果要确定内存泄漏发生的位置,请使用分析器或编写单元测试和模拟对象。
编辑:为了获得智能指针的好处,您还必须挂钩或实现自己的垃圾收集器,因为它不是语言功能。
编辑2:智能指针显然实现了引用计数,这是一种垃圾收集策略。
答案 4 :(得分:0)
智能指针'代码'对象所有权的文档。因此,对于每个指针,您必须将“某些程序员头部的模糊文档”转换为“代码中的精确文档”。大多数选择都很简单。这仍然留下了许多不是的选择。此外,除了所有权之外,您还必须担心使用弱指针打破对象图循环。所以这种整体转换为智能指针并不是一项简单的任务,如果你让循环中断部分出错,你甚至会引入新的内存泄漏。