zoukankan      html  css  js  c++  java
  • 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 0;
    }
    
    A::A()
    {
        ofstream fout("test.txt");
        fout << "A constructed
    ";
        fout.close();
    }
    
    A::~A()
    {
        ofstream fout("test.txt", ios_base::app);
        fout << "A destructed
    ";
        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确实会造成内存泄漏。但也不必太担心,通常操作系统都会自动回收这些分配的内存(较老的就不会)。

  • 相关阅读:
    树莓派3(Raspbain系统)安装.net环境
    CSS3实现鼠标悬停扩展效果
    WINIO64位模拟键鼠操作
    json在线校验
    阿里云ali-oss图片增加水印
    babel使用中不想使用 严格模式 如何去除?
    记录移动端html界面中底部输入框触发焦点时键盘会把输入框遮挡的问题
    nodejs 项目,请求返回Invalid Host header问题
    css如何画出类似原生的线条?
    js回到顶部 动画速度 (自己记录)
  • 原文地址:https://www.cnblogs.com/collectionne/p/6785576.html
Copyright © 2011-2022 走看看