【问题标题】:C++ destructor and memory allocation, and undefined beahviourC++ 析构函数和内存分配,以及未定义的行为
【发布时间】:2014-04-19 21:42:14
【问题描述】:

首先:我知道如果一个对象的析构函数抛出了应用程序的行为就不能指望......问题是关于内存问题。

所以,现在这很清楚了:

查看应用程序:

#include <stdlib.h>
#include <iostream>

class T
{
    public:
        T() : ma(0) 
             {std::cout << "T::T ->default<-" << std::endl; }
        T(const char* a) : ma(a) 
             {std::cout << "T::T ->" << ma << "<-" << std::endl; }
        ~T() 
             {std::cout << "T::~T ->" << ma << "<-" << std::endl; }

    private:
        const char* ma;
};

int main()
{
    T* t = new T();

    delete t;
}

看看它的 valgrind 输出:

$ valgrind ./a.out
==29554== Memcheck, a memory error detector
==29554== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==29554== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==29554== Command: ./a.out
==29554== 
T::T ->default<-
T::~T ->==29554== 
==29554== HEAP SUMMARY:
==29554==     in use at exit: 0 bytes in 0 blocks
==29554==   total heap usage: 1 allocs, 1 frees, 4 bytes allocated
==29554== 
==29554== All heap blocks were freed -- no leaks are possible
==29554== 
==29554== For counts of detected and suppressed errors, rerun with: -v
==29554== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

解释:T::~T -&gt;==29554== 告诉我析构函数遇到了危险情况(std::cout 接受了一个未定义的空值)所以应用程序的行为是无法控制的......

由于它没有打印出 "&lt;-" 并且它立即给我 valgrind 提示,我希望它在那个特定点退出。 Valgrind 没有报告任何段错误或类似的东西......

而且,valgrind 报告没有内存泄漏......这让我很困惑......所以我认为发生的情况是:

  1. 我打电话给delete t;
  2. 应用程序释放内存 t
  3. t 的析构函数被调用。

你能解释一下这里发生了什么吗?

编辑:有一个更清楚的问题:

是在释放的内存上调用析构函数还是在 std::cout 获得空对象时析构函数中没有未定义的行为?

【问题讨论】:

标签: c++ memory valgrind destructor undefined-behavior


【解决方案1】:

未定义的行为是未定义的。

如果我不得不猜测,看起来,在这种情况下,流检测到空指针并进入错误状态,所以你根本看不到任何输出。删除过程的其余部分显然按预期继续。

其他形式的未定义行为,例如实际取消引用空指针,可能会产生不同的结果。同样,当您违反其要求时,其他流实现的行为可能会有所不同。

【讨论】:

  • 或者将它指向内存中的某个分配地址,然后在该内存中粘贴一些值
  • 是的……这就是问题所在。 std::cout (在这个(linux)平台上只是吃了空值并停止输出东西)。我将代码移到了另一台机器 (XP),它给出了分段错误。
【解决方案2】:

Valgrind 是对的,没有内存泄漏。

您在堆中分配了变量 t,但没有分配 T 类的内部工作。因此,由于您负责使用 delete 释放内存,因此析构函数没有可释放的内容。

您可以在Class T 中分配一个变量,而不是在析构函数中释放它以查看内存泄漏。

【讨论】:

  • 29554 是 valgrind 打印的进程 ID。
猜你喜欢
  • 2015-08-22
  • 2020-07-18
  • 1970-01-01
  • 1970-01-01
  • 2019-03-10
  • 2016-10-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多