delete, myArray addr: 0x55f9d504a0d0 delete, myArray addr: 0x55f9d504a0d0 free(): double free detected in tcache 2 [1] 9912 abort (core dumped) ./a.out

这里看到同一段堆内存被free了两次,使用valgrind工具检查也发现了frees比allocs多了一次:

$ valgrind --leak-check=yes ./a.out
==10533== HEAP SUMMARY:
==10533==     in use at exit: 0 bytes in 0 blocks
==10533==   total heap usage: 5 allocs, 6 frees, 74,344 bytes allocated
==10533==
==10533== All heap blocks were freed -- no leaks are possible
==10533==
==10533== For counts of detected and suppressed errors, rerun with: -v
==10533== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

出现这个问题的根本原因是 q.push(t), 当我们查看std::queue::push方法时,我们看到添加到队列的元素"初始化为 x 的副本"。它实际上是一个全新的对象,它使用复制构造函数复制原始对象的每个成员来制作一个新的 Test。默认情况下C++编译器会生成一个复制构造函数:当把所有变量值从旧对象复制到新对象时,就会有两个指针指向内存中的同一个数组。这本质上并不坏,但析构函数将尝试删除同一个数组两次,因此出现"double free detected"运行时错误。

解决方法一:添加copy constructor和copy-assignment operator

第一步是实现一个copy constructor,它可以安全地将数据从一个对象复制到另一个对象。它可能看起来像这样:

Test(const Test &other)
    myArray = new int[10];
    memcpy(myArray, other.myArray, 10);

现在在复制 Test 对象时,将为新对象分配一个新数组,并且也会复制数组的值。但是把Test对象赋值给另外一个对象时,编译器可能会导致类似的问题,所以我们要同样实现一个copy-assignment operator,看起来像是这样:

Test &operator=(const Test &other)
    myArray = new int[10];
    if (this != &other)
        memcpy(myArray, other.myArray, 10);
    return *this;

这里的重要部分是,我们将其他数组中的数据复制到此对象的数组中,使每个对象的内存保持独立,这样析构函数永远不会删除同一个数组两次。

解决方法二(推荐):使用智能指针

智能指针是存储指向动态分配(堆)对象指针的类。除了能够在适当的时间自动删除指向的对象外,他们的工作机制很像C++的内置指针。智能指针在面对异常的时候格外有用,因为他们能够确保正确的销毁动态分配的对象。他们也可以用于跟踪被多用户共享的动态分配对象。我们尝试用boost库里面的智能指针来解决本文提到的问题,看起来像这样:

#include <queue>
#include <cstring>
#include <iostream>
#include <boost/shared_array.hpp>
using namespace std;
class Test
    int *myArray;
public:
    Test()
        boost::shared_array<int> myArray1(new int[10]);
        myArray = myArray1.get();
        std::cout << "myArray addr " << myArray << std::endl;
int main()
    queue<Test> q;
    Test t;
    q.push(t);

编译后使用valgrind工具检查可以发现堆内存的allocs和frees是一一对应的:

$ valgrind --leak-check=yes ./a.out
==21832== Memcheck, a memory error detector
==21832== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==21832== Command: ./a.out
==21832==
myArray addr 0x5b7ff40
==21832==
==21832== HEAP SUMMARY:
==21832==     in use at exit: 0 bytes in 0 blocks
==21832==   total heap usage: 6 allocs, 6 frees, 74,376 bytes allocated
==21832==
==21832== All heap blocks were freed -- no leaks are possible
==21832==
==21832== For counts of detected and suppressed errors, rerun with: -v
==21832== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
                    最近在项目中遇到了“free(): double free detected”问题,出问题的代码类似于:#include &lt;queue&gt;#include &lt;cstring&gt;#include &lt;iostream&gt;using namespace std; class Test{    int *myArray; public:    Test() { myArray = new int[10]; }     ~Test()    {       
free():在tcache 2中检测到双空闲,在执行程序的过程中对同一块内存单元进行了两次free()操作。
在循环中包含free();语句,容易出现这类问题。
可以设置两个指针,进行操作,下面给出示范
出现double free() 的报错
只设置了一个指针变量n,在循环的过程中,会再次对n进行free();操作因此会出现此次问题
double free()得到解决
设置两个指针变量,
				
在日常编码过程中会遇见各种编译错误,本文对常见的编译错误进行分析总结。(基本的编译错误在这里不列举,后续后持续更新)1、error c101008a解决方法该错误出现在项目升级过程中会出现,比如说项目从vs2008升级到vs2010.解决办法:在项目上点右键,清理(Clean),重新编译,问题解决2、error C2252解决方法该错误主要在项目从vs2008升级到vs2010出先。error C2252: an explicit instantiation of a template can only occur at namespace scope解决方法:将特例话的模板移到类外面(It
#0 0xf7eea129 in __kernel_vsyscall () #1 0xf6f200f6 in raise () from /lib/libc.so.6 #2 0xf6f09dd4 in abort () from /lib/libc.so.6 #3 0xf6f64a7c in __libc_message () from /lib/libc.so.6 #4 0xf6f6c57f in malloc_printerr () from /lib/libc.so.6 #5 0xf6f6
baseDMA Shirt("Portabelly", 8); baseDMA Shirt2 = Shirt; // only invokecopy constructor Shirt2 = Shirt; // only invokeasignment constructor 二、编写注意的点: copy constructor 还是 asignment constructor, 如果自己不定义 编译器都会自动生成 defaultco... 1.如何选择需要使用的整数类型 C语言只规定了short存储的空间不能多于int,long存储空间不能少于int。目前个人计算机最常见的设置是long long占64位,long占32位,short占16位,int占16位或者32位。 选取的原则如下: 如果是非负值,首先考虑unsigned类型,因为它可以表示更大的整数 如果超出了int类型的取值范围,但又在long...