Assert与内存泄漏
以前知道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与内存泄漏的更多相关文章
- C语言中的指针和内存泄漏
引言 对于任何使用C语言的人,如果问他们C语言的最大烦恼是什么,其中许多人可能会回答说是指针和内存泄漏.这些的确是消耗了开发人员大多数调试时间的事项.指针和内存泄漏对某些开发人员来说似乎令人畏惧,但是 ...
- VS2005内存泄漏检测方法[转载]
一.非MFC程序可以用以下方法检测内存泄露: 1. 程序开始包含如下定义: #ifdef _DEBUG #define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __ ...
- (转)从内存管 理、内存泄漏、内存回收探讨C++内存管理
http://www.cr173.com/html/18898_all.html 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟 ...
- c++内存泄漏处理(积累)
写c++程序时,常常会出现内存泄漏的问题,这里从网上找了一种非常麻烦的方法:假设想找到每一个cpp文件的内存泄漏,都必须在每一个cpp加上例如以下代码: #include <crtdbg.h&g ...
- C++中内存泄漏的检测方法介绍
C++中内存泄漏的检测方法介绍 首先我们需要知道程序有没有内存泄露,然后定位到底是哪行代码出现内存泄露了,这样才能将其修复. 最简单的方法当然是借助于专业的检测工具,比较有名如BoundsCheck, ...
- [C]C语言中的指针和内存泄漏几种情况
引言 原文地址:http://www.cnblogs.com/archimedes/p/c-point-memory-leak.html,转载请注明源地址. 对于任何使用C语言的人,如果问他们C语言的 ...
- C/C++的内存泄漏检测工具Valgrind memcheck的使用经历
Linux下的Valgrind真是利器啊(不知道Valgrind的请自觉查看参考文献(1)(2)),帮我找出了不少C++中的内存管理错误,前一阵子还在纠结为什么VS 2013下运行良好的程序到了Lin ...
- C语言中的指针和内存泄漏几种情况
引言 原文地址:http://www.cnblogs.com/archimedes/p/c-point-memory-leak.html,转载请注明源地址. 对于任何使用C语言的人,如果问他们C语言的 ...
- 内存泄漏(memory leak)和内存溢出
1. 什么是内存泄漏(memory leak)? 指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况.内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存 ...
随机推荐
- 安装ruby compass失败
安装compass失败 ERROR: Could not ), here is why: Unable to download data from https://rubygems.org/ - SS ...
- STM32、Cortex-A、Cortex-R、Cortex-M、SecurCore
STM32是就是基于Cortex-M3这个核生产的CPU. arm7是arm公司推出的以V4指令集设计出来的arm核--其代表的芯片有s3c44b0 arm9是arm公司推出的以V5指令集设计出来的a ...
- JavaWeb的国际化(17/4/8)
国际化的缺点: 因为文字不同,所以带来的排版问题一样严重,通常都是重新在写一个网站反而更加清晰,快捷 1:需要从浏览器中获取到浏览器语言(Accept-Language) 2:利用locale获取 ...
- DbVisualizer:Oracle触发器,解决ORA-04098: 触发器 'USER.DECTUSERTEST_TRI' 无效且未通过重新验证
我没有用orcal的管理工具,而是用的DbVisualizer 9.5.2,管理数据库. 场景:需要在oracle里面实在自增字段,在网上一搜一堆文档,然后自己就找了一段自己写如下: drop tab ...
- [CTSC2008] 网络管理
题目描述 Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构 ...
- JQuery获取元素类名
一般而言,JQuery可以利用attr来获取元素的属性值, 1.$("元素").attr("属性"); //获取指定属性的值 2. ...
- TypeScript入门-枚举、类型推论
枚举 使用枚举可以定义一些具有名字的数字常量,和在C语言中一样都是使用关键字enum enum Direction { Up = 1, Down = 1<<2, Left, Right } ...
- Spark机器学习之协同过滤算法
Spark机器学习之协同过滤算法 一).协同过滤 1.1 概念 协同过滤是一种借助"集体计算"的途径.它利用大量已有的用户偏好来估计用户对其未接触过的物品的喜好程度.其内在思想是相 ...
- js,jQuery和DOM操作的总结(一)
废话不说,直接上图 一 js的基本操作 (1)js 的六种数据类型 var n4;//六种数据类型用typeof来确定类型,Null类型的用typeof是不行的,这个是特殊 alert(typeof ...
- ural 1297. Palindrome
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1297 求最长回文子串 典型的后缀数组的入门题目,但是可以用更简单的方法解决,毕竟数据量比 ...