如何在C ++代码/项目中查找内存泄漏?


180

我是Windows平台上的C ++程序员。我正在使用Visual Studio 2008。

我通常会在代码中出现内存泄漏。

通常,我可以通过检查代码来发现内存泄漏,但这很麻烦,而且并不总是一种好的方法。

由于我买不起付费的内存泄漏检测工具,因此我希望你们提出避免内存泄漏的最佳方法。

  1. 我想知道程序员如何发现内存泄漏。
  2. 是否应遵循任何标准或程序以确保程序中没有内存泄漏?

29
“我通常会在代码中出现内存泄漏。” 如果使用自动变量,容器和智能指针(并遵循使用智能指针的最佳实践),则内存泄漏应该非常少见。请记住,几乎在所有情况下,您都应该使用自动资源管理
James McNellis 2011年


1
@Hostile Fork:这些答案未涵盖“如何避免通常导致内存泄漏的代码”。
布朗

2
@doc布朗:不喜欢看的是涨得,但它的所有其他地方覆盖,如stackoverflow.com/questions/45627/...
HostileFork表示不信任SE

1
DIY泄漏检测器:您可以将可疑代码放入无限循环中,然后打开任务管理器,通常即使是很小的泄漏也会在几秒钟或几分钟内填满内存(这取决于您的代码复杂性和CPU)。如果那没有发生,那段代码可能不会泄漏。
世界世界你好

Answers:


269

使用说明

您需要的东西

  • 精通C ++
  • C ++编译器
  • 调试器和其他调查软件工具

1个

了解操作员的基本知识。C ++运算符new分配堆内存。该delete运营商的FreeS堆内存。对于each new,您应该使用a,delete以便释放分配的相同内存:

char* str = new char [30]; // Allocate 30 bytes to house a string.

delete [] str; // Clear those 30 bytes and make str point nowhere.

2

仅在删除后才重新分配内存。在下面的代码中,str使用第二个分配获取一个新地址。第一个地址丢失是无法挽回的,它指向的30个字节也是如此。现在它们无法释放,并且您会发生内存泄漏:

char* str = new char [30]; // Give str a memory address.

// delete [] str; // Remove the first comment marking in this line to correct.

str = new char [60]; /* Give str another memory address with
                                                    the first one gone forever.*/

delete [] str; // This deletes the 60 bytes, not just the first 30.

3

观看那些指针分配。每个动态变量(堆上已分配的内存)都需要与一个指针相关联。当动态变量与其指针解除关联时,将无法擦除。同样,这会导致内存泄漏:

char* str1 = new char [30];

char* str2 = new char [40];

strcpy(str1, "Memory leak");

str2 = str1; // Bad! Now the 40 bytes are impossible to free.

delete [] str2; // This deletes the 30 bytes.

delete [] str1; // Possible access violation. What a disaster!

4

注意局部指针。您在函数中声明的指针分配在堆栈上,但是它指向的动态变量分配在堆上。如果不删除它,它将在程序退出该函数后继续存在:

void Leak(int x){

char* p = new char [x];

// delete [] p; // Remove the first comment marking to correct.

}

5

注意“删除”后的方括号。delete单独使用以释放单个对象。delete []与方括号一起使用以释放堆数组。不要做这样的事情:

char* one = new char;

delete [] one; // Wrong

char* many = new char [30];

delete many; // Wrong!

6

如果泄漏尚未被允许-我通常会与deleaker一起寻求它(请在此处进行检查:http ://deleaker.com )。


3
很抱歉提出问题,但是没有指针的函数参数呢?someFunction("some parameter")我不得不删除"some parameter"someFunction,在函数调用后,或者在这些自动删除?
19greg96

1
感谢您与Deleaker的链接,这是一个非常方便的工具,可以很好地集成到Visual Studio中。我可以节省很多时间。向我指出了分配内存但没有释放内存的行。大。与我发现的其他内存泄漏查找器相比,它很便宜。
this.myself15年

@ john smith plz explan处理类似于案例3的案例的正确方法是什么?str2 = str1; //不好!现在这40个字节已无法释放。如何删除str 1然后?
Nihar

1
如果我们使用char *,int,float等值类型以及Vector,CString这样的结构类型,并且根本不使用任何'new'运算符,那不会导致内存泄漏,对吗?
123iamking '16

我只是在这里说我已经14年没有接触过c ++了...但是我很自豪地说,由于我仍然拥有和阅读的一本c ++书,我了解并记住了如何做所有这些事情。我对C#感到厌烦。那本书是斯科特·米切尔(Scott Mitchell)的《有效C ++》。上帝,我喜欢那本书。谢谢斯科特!
JonH

33

您可以在代码中使用某些技术来检测内存泄漏。最常见和最简单的检测方法是,定义一个宏DEBUG_NEW并使用它,以及预定义的宏(例如)__FILE____LINE__在代码中查找内存泄漏。这些预定义的宏告诉您内存泄漏的文件和行数。

DEBUG_NEW只是一个宏,通常定义为:

#define DEBUG_NEW new(__FILE__, __LINE__)
#define new DEBUG_NEW

这样,无论您在哪里使用new它,都可以跟踪文件和行号,这些文件和行号可用于定位程序中的内存泄漏。

而且__FILE____LINE__预定义宏在您使用它们分别评估的文件名和行号!

阅读以下文章,它非常精美地介绍了将DEBUG_NEW与其他有趣的宏配合使用的技术:

跨平台内存泄漏检测器


Wikpedia

Debug_new是C ++中的一种技术,用于重载和/或重新定义运算符new和operator delete,以拦截内存分配和释放操作,从而调试程序以使用内存。它通常涉及定义一个名为DEBUG_NEW的宏,并使new成为类似于new(_ FILE _,_ LINE _)之类的东西,以记录有关分配的文件/行信息。Microsoft Visual C ++在其Microsoft基础类中使用了此技术。有一些方法可以扩展此方法,从而避免使用宏重新定义,同时仍然能够在某些平台上显示文件/行信息。这种方法有很多固有的局限性。它仅适用于C ++,并且无法通过malloc之类的C函数捕获内存泄漏。但是,与某些更完整的内存调试器解决方案相比,它使用起来非常简单,而且非常快。


4
#define将导致过载operator new并产生编译器错误。即使您成功克服了这一点,仍然无法解决重载的功能。尽管该技术不错,但有时仍需要大量代码更改。
iammilind 2011年

1
@iammilind:当然,这种技术并不是所有问题的全能解决方案,并且肯定不适用于所有情况。
Nawaz

@Chris_vr:auto_ptr不会用标准容器,如工作std::vectorstd::list等看到这个:stackoverflow.com/questions/111478/...
纳瓦兹·

好酷 描述文件和行。operator new您正在使用的是什么版本?这些版本是什么?

14

有一些著名的编程技术可以帮助您最大程度地降低第一手获得内存泄漏的风险:

  • 如果必须自己进行动态内存分配,请始终成对写入newdelete始终成对进行,并确保分配/解除分配代码成对调用
  • 如果可以,请避免动态分配内存。例如,vector<T> t尽可能使用而不是T* t = new T[size]
  • 使用“智能指针”之类的增强智能指针(http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/smart_ptr.htm
  • 我个人最喜欢的:确保您已经了解了指针所有权的概念,并确保在使用指针的任何地方都知道哪个代码实体是所有者
  • 了解哪些构造函数/赋值运算符会自动由C ++编译器,什么创造这意味着,如果你有拥有一个指针类(或者是什么意思,如果你有一个包含一个指向对象它一类自己)。

我使用对象的auto_pointer确实意味着它将删除其中的所有其他类对象指针。
Chris_vr 2011年

@Chris_vr:如果您对auto_pointer有特定疑问,建议您提出一个新问题,包括一个示例。
布朗

许多帖子告诉我,vector <>不能保证清除后释放内存。我亲自测试了交换内容等,得出的结论是vector <>正在泄漏,尤其是在动态使用时。我不明白如何使用“ new”和正确清除方法自行建议vector <>进行动态分配。在我的嵌入式程序中,由于所有泄漏,我避免将vector <>用于动态内容。在那里,我使用new或std :: list
bart s

由于字符数的原因,我键入了第二个命令。使用矢量<>动态内存耗尽时,不幸的是++我的嵌入式C ++我有一个老C(?98)不具有shrink_to_fit上的向量...然而,嵌入式程序是100%肯定完全崩溃
巴特小号


8
  1. 下载Windows调试工具
  2. 使用该gflags实用程序打开用户模式堆栈跟踪。
  3. UMDH把你的程序的内存的多个快照。在分配内存之前拍摄快照,并在您认为程序泄漏内存之后拍摄第二张快照。您可能希望在程序中添加暂停或提示,以便有机会运行UMDH和拍摄快照。
  4. UMDH再次运行,这次以在两个快照之间进行区别的模式运行。然后它将生成一个报告,其中包含可疑内存泄漏的调用堆栈。
  5. 完成后,还原以前的gflags设置。

UMDH与CRT调试堆相比,它将为您提供更多信息,因为它正在监视整个过程中的内存分配;它甚至可以告诉您第三方组件是否泄漏。


1
我更喜欢Deleaker和Valgrind而不是标准分析器
z0r1fan

8

运行“ Valgrind”可以:

1)帮助识别内存泄漏 -向您显示您有多少内存泄漏,并指出代码中分配泄漏内存的行。

2)指出释放内存的错误尝试(例如的不正确调用delete

使用“ Valgrind”的说明

1)在这里获取valgrind 。

2)用-g标志编译代码

3)在您的shell中运行:

valgrind --leak-check=yes myprog arg1 arg2

其中“ myprog”是您的已编译程序,并且arg1arg2您程序的参数。

4)结果是malloc/ 的呼叫列表new,没有随后的免费删除呼叫。

例如:

==4230==    at 0x1B977DD0: malloc (vg_replace_malloc.c:136)

==4230==    by 0x804990F: main (example.c:6)

告诉您在哪一行malloc(未释放)被调用。

正如其他人指出的,请确保对于每个new/ malloc呼叫,您都有一个后续delete/ free呼叫。


6

如果您使用gcc,则可以使用gprof。

我想知道程序员如何发现内存泄漏

有些使用工具,有些做您的工作,也可以通过对等代码审查

是否应遵循任何标准或程序以确保程序中没有内存泄漏

对我来说:每当创建动态分配的对象时,我总是将释放代码放在后面,然后在它们之间填充代码。如果您确定两者之间的代码中没有异常,则可以。否则,我会尝试使用try-finally(我不经常使用C ++)。


有时我们无法删除构造函数中分配的值,那时候该怎么做。
Chris_vr 2011年

5
  1. 在Visual Studio中,有一个用于内存泄漏的内置检测器,称为C运行时库。当主函数返回后程序退出时,CRT将检查应用程序的调试堆。如果您在调试堆上仍分配了任何块,则内存泄漏。

  2. 该论坛讨论了避免C / C ++中内存泄漏的几种方法。


5

在代码中搜索的出现new,并确保它们全部在构造函数中发生,并且在析构函数中具有匹配的删除。确保这是该构造函数中唯一可能的抛出操作。一种简单的方法是将所有指针包装在std::auto_ptr或中boost::scoped_ptr(取决于您是否需要移动语义)。对于所有将来的代码,只需确保每个资源都由一个在其析构函数中清除该资源的对象拥有。如果需要移动语义,则可以升级到支持r值引用的编译器(我相信VS2010)并创建移动构造函数。如果您不想这样做,则可以使用各种棘手的技术,包括认真使用swap,或者尝试使用Boost.Move库。


并非总是可以在构造函数中删除分配的内存。如何处理这种情况
Chris_vr11年

@Chris_vr是什么意思?如果您的所有指针成员都是scope_ptrs,并且每个成员都分别进行初始化,则所有成功构建的成员将删除其指针,而其他成员仍将不持有指向已分配内存的指针。下班回家后的几个小时,我将举一个例子。
Mankarse 2011年

@Chris_vr:如果您有特定的示例,请将其发布为新问题,以便我们在此处进行讨论。
Doc Brown

5

您可以使用Valgrind工具检测内存泄漏。

另外,要查找特定函数中的泄漏,请在函数末尾使用exit(0),然后使用Valgrind运行它

`$` valgrind ./your_CPP_program 

5

自动内存泄漏检查器概述

在这个答案中,我在一个简单易懂的内存泄漏示例中比较了几种不同的内存泄漏检查器。

首先,请参阅ASan Wiki中的这张巨大表格,其中比较了人类已知的所有工具:https : //github.com/google/sanitizers/wiki/AddressSanitizerComparisonOfMemoryTools/d06210f759fec97066888e5f27c7e722832b0924

分析的示例将是:

main.c

#include <stdlib.h>

void * my_malloc(size_t n) {
    return malloc(n);
}

void leaky(size_t n, int do_leak) {
    void *p = my_malloc(n);
    if (!do_leak) {
        free(p);
    }
}

int main(void) {
    leaky(0x10, 0);
    leaky(0x10, 1);
    leaky(0x100, 0);
    leaky(0x100, 1);
    leaky(0x1000, 0);
    leaky(0x1000, 1);
}

GitHub上游

我们将尝试看看不同的工具将我们指向泄漏的呼叫有多清晰。

Google的gperftools提供的tcmalloc

https://github.com/gperftools/gperftools

在Ubuntu 19.04上的用法:

sudo apt-get install google-perftools
gcc -ggdb3 -o main.out main.c -ltcmalloc
PPROF_PATH=/usr/bin/google-pprof \
  HEAPCHECK=normal \
  HEAPPROFILE=ble \
  ./main.out \
;
google-pprof main.out ble.0001.heap --text

程序运行的输出包含内存泄漏分析:

WARNING: Perftools heap leak checker is active -- Performance may suffer
Starting tracking the heap
Dumping heap profile to ble.0001.heap (Exiting, 4 kB in use)
Have memory regions w/o callers: might report false leaks
Leak check _main_ detected leaks of 272 bytes in 2 objects
The 2 largest leaks:
Using local file ./main.out.
Leak of 256 bytes in 1 objects allocated from:
        @ 555bf6e5815d my_malloc
        @ 555bf6e5817a leaky
        @ 555bf6e581d3 main
        @ 7f71e88c9b6b __libc_start_main
        @ 555bf6e5808a _start
Leak of 16 bytes in 1 objects allocated from:
        @ 555bf6e5815d my_malloc
        @ 555bf6e5817a leaky
        @ 555bf6e581b5 main
        @ 7f71e88c9b6b __libc_start_main
        @ 555bf6e5808a _start


If the preceding stack traces are not enough to find the leaks, try running THIS shell command:

pprof ./main.out "/tmp/main.out.24744._main_-end.heap" --inuse_objects --lines --heapcheck  --edgefraction=1e-10 --nodefraction=1e-10 --gv

If you are still puzzled about why the leaks are there, try rerunning this program with HEAP_CHECK_TEST_POINTER_ALIGNMENT=1 and/or with HEAP_CHECK_MAX_POINTER_OFFSET=-1
If the leak report occurs in a small fraction of runs, try running with TCMALLOC_MAX_FREE_QUEUE_SIZE of few hundred MB or with TCMALLOC_RECLAIM_MEMORY=false, it might help find leaks more re
Exiting with error code (instead of crashing) because of whole-program memory leaks

的输出google-pprof包含堆使用情况分析:

Using local file main.out.
Using local file ble.0001.heap.
Total: 0.0 MB
     0.0 100.0% 100.0%      0.0 100.0% my_malloc
     0.0   0.0% 100.0%      0.0 100.0% __libc_start_main
     0.0   0.0% 100.0%      0.0 100.0% _start
     0.0   0.0% 100.0%      0.0 100.0% leaky
     0.0   0.0% 100.0%      0.0 100.0% main

输出将我们指向三个泄漏中的两个:

Leak of 256 bytes in 1 objects allocated from:
        @ 555bf6e5815d my_malloc
        @ 555bf6e5817a leaky
        @ 555bf6e581d3 main
        @ 7f71e88c9b6b __libc_start_main
        @ 555bf6e5808a _start
Leak of 16 bytes in 1 objects allocated from:
        @ 555bf6e5815d my_malloc
        @ 555bf6e5817a leaky
        @ 555bf6e581b5 main
        @ 7f71e88c9b6b __libc_start_main
        @ 555bf6e5808a _start

我不确定为什么第三个没有出现

无论如何,通常情况下,当某件事泄漏时,它会发生很多次,而当我在真实的项目中使用它时,我最终很容易被指出泄漏功能。

如输出本身所提到的,这会导致执行速度显着下降。

更多文档,请访问:

另请参阅:如何使用TCMalloc?

在Ubuntu 19.04中测试,google-perftools 2.5-2。

Google也提供地址消毒剂(ASan)

https://github.com/google/sanitizers

先前在以下文章中提到:如何在C ++代码/项目中查找内存泄漏?TODO与tcmalloc。

这已经集成到GCC中,因此您可以执行以下操作:

gcc -fsanitize=address -ggdb3 -o main.out main.c
./main.out 

和执行输出:

=================================================================
==27223==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 4096 byte(s) in 1 object(s) allocated from:
    #0 0x7fabbefc5448 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10c448)
    #1 0x55bf86c5f17c in my_malloc /home/ciro/test/main.c:4
    #2 0x55bf86c5f199 in leaky /home/ciro/test/main.c:8
    #3 0x55bf86c5f210 in main /home/ciro/test/main.c:20
    #4 0x7fabbecf4b6a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26b6a)

Direct leak of 256 byte(s) in 1 object(s) allocated from:
    #0 0x7fabbefc5448 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10c448)
    #1 0x55bf86c5f17c in my_malloc /home/ciro/test/main.c:4
    #2 0x55bf86c5f199 in leaky /home/ciro/test/main.c:8
    #3 0x55bf86c5f1f2 in main /home/ciro/test/main.c:18
    #4 0x7fabbecf4b6a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26b6a)

Direct leak of 16 byte(s) in 1 object(s) allocated from:
    #0 0x7fabbefc5448 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10c448)
    #1 0x55bf86c5f17c in my_malloc /home/ciro/test/main.c:4
    #2 0x55bf86c5f199 in leaky /home/ciro/test/main.c:8
    #3 0x55bf86c5f1d4 in main /home/ciro/test/main.c:16
    #4 0x7fabbecf4b6a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26b6a)

SUMMARY: AddressSanitizer: 4368 byte(s) leaked in 3 allocation(s).

清楚地标识所有泄漏。真好!

ASan还可以进行其他出色的检查,例如越界写入:检测到堆栈粉碎

已在Ubuntu 19.04,GCC 8.3.0中测试。

瓦尔格朗德

http://www.valgrind.org/

先前在以下位置提到过:https : //stackoverflow.com/a/37661630/895245

用法:

sudo apt-get install valgrind
gcc -ggdb3 -o main.out main.c
valgrind --leak-check=yes ./main.out

输出:

==32178== Memcheck, a memory error detector
==32178== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==32178== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==32178== Command: ./main.out
==32178== 
==32178== 
==32178== HEAP SUMMARY:
==32178==     in use at exit: 4,368 bytes in 3 blocks
==32178==   total heap usage: 6 allocs, 3 frees, 8,736 bytes allocated
==32178== 
==32178== 16 bytes in 1 blocks are definitely lost in loss record 1 of 3
==32178==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==32178==    by 0x10915C: my_malloc (main.c:4)
==32178==    by 0x109179: leaky (main.c:8)
==32178==    by 0x1091B4: main (main.c:16)
==32178== 
==32178== 256 bytes in 1 blocks are definitely lost in loss record 2 of 3
==32178==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==32178==    by 0x10915C: my_malloc (main.c:4)
==32178==    by 0x109179: leaky (main.c:8)
==32178==    by 0x1091D2: main (main.c:18)
==32178== 
==32178== 4,096 bytes in 1 blocks are definitely lost in loss record 3 of 3
==32178==    at 0x483874F: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==32178==    by 0x10915C: my_malloc (main.c:4)
==32178==    by 0x109179: leaky (main.c:8)
==32178==    by 0x1091F0: main (main.c:20)
==32178== 
==32178== LEAK SUMMARY:
==32178==    definitely lost: 4,368 bytes in 3 blocks
==32178==    indirectly lost: 0 bytes in 0 blocks
==32178==      possibly lost: 0 bytes in 0 blocks
==32178==    still reachable: 0 bytes in 0 blocks
==32178==         suppressed: 0 bytes in 0 blocks
==32178== 
==32178== For counts of detected and suppressed errors, rerun with: -v
==32178== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

因此,再次检测到所有泄漏。

另请参阅:如何使用valgrind查找内存泄漏?

在Ubuntu 19.04,valgrind 3.14.0中进行了测试。


4

Visual Leak Detector(VLD)是一个免费的,健壮的,开放源代码的Visual C ++内存泄漏检测系统。

当您在Visual Studio调试器下运行程序时,Visual Leak Detector将在调试会话结束时输出内存泄漏报告。泄漏报告包括完整的调用堆栈,该堆栈显示了如何分配泄漏的内存块。双击调用堆栈中的一行以跳转到该文件,然后在编辑器窗口中一行。

如果只有崩溃转储,则可以使用Windbg !heap -l命令,它将检测泄漏的堆块。最好打开gflags选项:“创建用户模式堆栈跟踪数据库”,然后您将看到内存分配调用堆栈。


4

MTuner是一个免费的多平台内存配置文件,泄漏检测和分析工具,支持MSVC,GCC和Clang编译器。功能包括:

  • 基于时间线的内存使用和活动内存块历史
  • 基于堆,内存标签,时间范围等的强大的内存操作过滤
  • 用于手动检测的SDK,带有完整的源代码
  • 通过命令行使用提供持续集成支持
  • 调用堆栈树和树图导航
  • 多得多。

用户可以使用GCC或Clang交叉编译器来分析针对平台的任何软件。MTuner内置了对Windows,PlayStation 4和PlayStation 3平台的支持。


这应该是公认的答案。这是一个很好的工具,可以处理其他人无法处理的大量分配/取消分配。
Serge Rogatch

3

在Windows上,您可以使用CRT调试堆

是否应遵循任何标准或程序以确保程序中没有内存泄漏。

是的,不要使用手动内存管理(如果您曾经打电话deletedelete[]手动,那么您做错了)。使用RAII和智能指针,将堆分配限制为绝对最小值(大多数情况下,自动变量就足够了)。


3

回答问题的第二部分,

是否应遵循任何标准或程序以确保程序中没有内存泄漏。

就在这里。这是C和C ++之间的主要区别之一。

在C ++中,永远不要调用newdelete在用户代码中。RAII是一种非常常用的技术,几乎解决了资源管理问题。程序中的每个资源(资源是必须获取的所有资源,然后再发布:文件句柄,网络套接字,数据库连接,还包括普通内存分配,在某些情况下还包括成对的API调用(BeginX( )/ EndX(),LockY(),UnlockY())应该包装在一个类中,其中:

  • 构造函数获取资源(通过调用new资源是否为内存分配)
  • 析构函数释放资源,
  • 防止复制和分配(通过将复制构造函数和赋值运算符设为私有),或者实现复制和分配以正常工作(例如,通过克隆基础资源)

然后,可以在本地,在堆栈上或作为类成员实例化该类,而不是通过调用new和存储指针来实例化。

您通常不需要自己定义这些类。标准库容器也以这种方式运行,以便std::vector在销毁向量时释放存储在中的任何对象。同样,不要将指针存储在容器中(这将要求调用newdelete),而是将对象本身(将为您提供免费的内存管理)存储。同样,智能指针类可用于轻松包装仅需使用分配的对象new,并控制其生命周期。

这意味着,当对象超出范围时,它将被自动销毁,并释放和清理其资源。

如果您在整个代码中始终如一地执行此操作,则根本不会发生任何内存泄漏。这一切都可以控制叶子范围在该对象被宣布时调用得到泄露被绑定到这是保证析构函数。


如果智能指针包含一个类,并且该类包含其他几个类的指针。当智能关闭时,这意味着里面的所有指针将被安全删除。
Chris_vr 2011年

@Chris:假定智能指针指向的对象具有析构函数,该析构函数执行必要的清理,或者该对象包含本身具有析构函数的成员,以执行必要的清理。本质上,只要每个对象都照顾好自己(在销毁对象后对其进行清理),并且只要每个对象都按值存储而不是作为指针存储,则需要释放的所有内容都会被释放。
jalf

3

AddressSanitizer(ASan)是一种快速内存错误检测器。它会在C / C ++程序中发现释放后使用和{heap,stack,global} -buffer溢出错误。它发现:

  • 释放后使用(悬空指针取消引用)
  • 堆缓冲区溢出
  • 堆栈缓冲区溢出
  • 全局缓冲区溢出
  • 退货后使用
  • 初始化订单错误

这个工具非常快。所检测程序的平均速度降低约2倍。



0

除了其他答案中提供的工具和方法外,静态代码分析工具还可用于检测内存泄漏(以及其他问题)。免费的强大工具是Cppcheck。但是,还有许多其他工具可用。Wikipedia列出了静态代码分析工具。


-1

确保所有堆内存都已成功释放。如果您从不在堆上分配内存,则没有必要。如果这样做,请计算分配内存的次数,并计算释放内存的次数。


-3

应用程序代码中不得使用“新”或“删除”。相反,创建一个使用管理器/工作器惯用语的新类型,其中管理器类分配和释放内存,并将所有其他操作转发给工作器对象。

不幸的是,这比应做的工作更多,因为C ++没有“ operator”的重载。在存在多态性的情况下,这甚至是更多的工作。

但这值得付出努力,因为您再也不必担心内存泄漏,这意味着您甚至不必寻找它们。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.