以前知道C/C++有assert之后,我想知道assert会不会造成内存泄漏,于是我做了一个测试:

#include <iostream>
#include <fstream>
#include <cassert>
using namespace std; class A
{
public:
A();
~A();
}; int main()
{
A a;
assert(false); // let the program crash
return ;
} A::A()
{
ofstream fout("test.txt");
fout << "A constructed\n";
fout.close();
} A::~A()
{
ofstream fout("test.txt", ios_base::app);
fout << "A destructed\n";
fout.close();
}

如果想要直接检测是否会有内存泄漏,是很难的,一般都需要借助一些相关软件的帮助。因此这里我们检测的是类的析构函数是否被调用,而析构函数(和构造函数)会向文本文件输出信息。程序运行完毕后,检查该文本文件,如果有A destructed这句话,就表示析构函数被调用了。

注意这里使用的是输出信息到文件而不是控制台。因为如果是控制台你是来不及看到相应消息的,除非暂停程序。(个人喜好问题)

还有一个需要注意的点(在A::~A()中):

ofstream fout("test.txt", ios_base::app);

因为构造函数会打开test.txt并输出,为了保留原来的内容并在文本末尾追加信息,使用了ios_base::app。

那么运行情况如何?

运行程序,和预期一样,弹出了错误框,程序停止。检查一下输出的test.txt,内容如下:

A constructed.

没有见到A destructed,说明构造函数根本没有被调用!对于A类还没什么,但对于STL的string、vector、map这些类来说,它们new的内存会在析构函数里delete,这不就会造成内存泄漏吗?!

是的,没错。

这时就需要Stack Overflow了。我刚刚在上面查到了一篇文章,看来以后要多上上Stack Overflow。

这是Stack Overflow上的回答:

1.

Assert on failure, writes the error to stderr and calls abort(). which unlike exit() doesn't execute the functions registered with atexit(), nor does it call destructors.
Hence, none of your destructors, clean-up code etc can be called. So it is up to the OS, as the memory isn't freed by the program, before its "unexpected" termination.

This is probably by design, as calling destructors might result in some further error. It terminates at that failed assert, executing no further code.

Assert失败时,将错误输出到stderr然后调用abort()。和exit()不同,abort()不执行atexit()注册的函数,或者调用析构函数。因此,你的析构函数、清理代码都不会被执行。所以这就需要靠OS(操作系统)了,因为内存不是在“意外的”结束之前由程序释放的。

这也许是故意设计的,因为调用析构函数可能会出现更多的错误。它(指程序)在失败的assert处停止,不再执行更多代码。

2.

The memory stays allocated as the assert failure brings down your program.

As part of destroying the process, any modern desktop OS will reclaim the memory. Some embedded operating systems might not be able to do this, although I don't have the name of one on hand.

You can detect memory that has to be reclaimed by the OS this way by using a utility such as Valgrind.

Assert失败并使你的程序崩溃时,内存仍然保留着。

作为毁灭进程的一部分,任何现代桌面OS都会收回这些内存。有些嵌入的操作系统(不知道有没有翻错)可能不能这么做,虽然我举不出这样的OS的名字。

你可以使用一个像Valgrind一样的工具检测因为这种原因需要被OS收回的内存。

--------------------------------------------------------------------------------

看完这些答案,说明了一个事实:assert确实会造成内存泄漏。但也不必太担心,通常操作系统都会自动回收这些分配的内存(较老的就不会)。

Assert与内存泄漏的更多相关文章

  1. C语言中的指针和内存泄漏

    引言 对于任何使用C语言的人,如果问他们C语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是 ...

  2. VS2005内存泄漏检测方法[转载]

    一.非MFC程序可以用以下方法检测内存泄露: 1. 程序开始包含如下定义: #ifdef _DEBUG #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __ ...

  3. (转)从内存管 理、内存泄漏、内存回收探讨C++内存管理

    http://www.cr173.com/html/18898_all.html 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟 ...

  4. c++内存泄漏处理(积累)

    写c++程序时,常常会出现内存泄漏的问题,这里从网上找了一种非常麻烦的方法:假设想找到每一个cpp文件的内存泄漏,都必须在每一个cpp加上例如以下代码: #include <crtdbg.h&g ...

  5. C++中内存泄漏的检测方法介绍

    C++中内存泄漏的检测方法介绍 首先我们需要知道程序有没有内存泄露,然后定位到底是哪行代码出现内存泄露了,这样才能将其修复. 最简单的方法当然是借助于专业的检测工具,比较有名如BoundsCheck, ...

  6. [C]C语言中的指针和内存泄漏几种情况

    引言 原文地址:http://www.cnblogs.com/archimedes/p/c-point-memory-leak.html,转载请注明源地址. 对于任何使用C语言的人,如果问他们C语言的 ...

  7. C/C++的内存泄漏检测工具Valgrind memcheck的使用经历

    Linux下的Valgrind真是利器啊(不知道Valgrind的请自觉查看参考文献(1)(2)),帮我找出了不少C++中的内存管理错误,前一阵子还在纠结为什么VS 2013下运行良好的程序到了Lin ...

  8. C语言中的指针和内存泄漏几种情况

    引言 原文地址:http://www.cnblogs.com/archimedes/p/c-point-memory-leak.html,转载请注明源地址. 对于任何使用C语言的人,如果问他们C语言的 ...

  9. 内存泄漏(memory leak)和内存溢出

    1. 什么是内存泄漏(memory leak)? 指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况.内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存 ...

随机推荐

  1. Ubuntu16.04安装NVIDIA驱动时的一些坑与解决方案

    这几天在新购置的笔记本上部署工作环境,在安装NVIDIA驱动的时候遇到了不少坑,重装了很多次,在Ubuntu论坛以及其他资料源看了很多大牛的分析,最终终于解决了一个又一个问题,过程比较艰辛,所以决定写 ...

  2. 找到一个新的超好用的U盘启动制作工具了

    有同事叫帮装电脑,弄个U盘说制作一个启动盘,结果一搜,出了“雨林木风”的主页. 太好用了,高手的产物,比以前找的方便一百倍.又简单,又实用,同步又下载好GHO文件.唯一 的问题是XP中用的GHO,好多 ...

  3. html 选择器之基础选择器

    我把CSS选择器分开成三部分,第一部分是我们常用的部分,我把他叫做基本选择器:第二部分我把他称作是属性选择器,第三部分我把他称作伪类选择器 一.基础选择器 1. 通配符(*):选中所有的元素 2.元素 ...

  4. Spring多种加载Bean方式简析

    1 定义bean的方式 常见的定义Bean的方式有: 通过xml的方式,例如: <bean id="dictionaryRelMap" class="java.ut ...

  5. git 分支的创建与提交

    我们在开发的过程中会遇到很多团队协作的问题,怎么来解决团队合作呢,就是靠分支来管理代码.一般来说一个功能就要创建一个分支,这样才能减少代码的冲突,给开发带来很大的方便. 首先需要克隆代码 git cl ...

  6. PowerDesigner 12.5破解方法

    PowerDesigner 12.5破解方法 创建于 2017-05-07 22:18:04   一.下载   1 . PowerDesigner 12.5 官方下载地址  http://downlo ...

  7. Python 与 C/C++ 交互的几种方式

    python作为一门脚本语言,其好处是语法简单,很多东西都已经封装好了,直接拿过来用就行,所以实现同样一个功能,用Python写要比用C/C++代码量会少得多.但是优点也必然也伴随着缺点(这是肯定的, ...

  8. C#集合之链表

    LinkedList<T>是一个双向链表,其元素会指向它前面和后面的元素.这样,通过移动到下一个元素可以正向遍历链表,通过移动到前一个元素可以反向遍历链表. 链表在存储元素时,不仅要存储元 ...

  9. OC—可变数组NSMutableArray

  10. Linux部分命令及通配符用法

    pwd: 显示工作目录 cd -: 在上一次所在目录与当前目录之间来回切换 cd: 切换回家目录 cat:  文本查看工具 -n:给显示的文本行编号 passwd 修改用户的密码 which 查看系统 ...