#include <vector>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
using namespace std;
class demo
{
public:
demo() :buffer(NULL)
{
buffer = new char[200];
strcpy(buffer, "hello world");
}
~demo()
{
if (buffer != NULL)
delete buffer;
buffer = NULL;
}
public:
char *buffer;
};
void fun()
{
demo a;
vector<demo> haha;
haha.push_back(a);
}
int main(int argc, char* argv[])
{
fun();
printf("执行完毕\r\n");
getchar();
return 0;
}
[root@]# g++ test1.cpp -g3 -O0
[root@]# ./a.out
*** Error in `./a.out': double free or corruption (!prev): 0x0000000001cc4010 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7c619)[0x7f3fa5f19619]
./a.out[0x400b09]
./a.out[0x400a2c]
./a.out[0x400a74]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f3fa5ebec05]
./a.out[0x400919]
======= Memory map: ========
00400000-00403000 r-xp 00000000 fd:00 151184408 /home/shiyuefeng/core/1/a.out
00602000-00603000 r--p 00002000 fd:00 151184408 /home/shiyuefeng/core/1/a.out
00603000-00604000 rw-p 00003000 fd:00 151184408 /home/shiyuefeng/core/1/a.out
01cc4000-01ce5000 rw-p 00000000 00:00 0 [heap]
7f3fa0000000-7f3fa0021000 rw-p 00000000 00:00 0
7f3fa0021000-7f3fa4000000 ---p 00000000 00:00 0
7f3fa5e9d000-7f3fa6055000 r-xp 00000000 fd:00 33597608 /usr/lib64/libc-2.17.so
7f3fa6055000-7f3fa6255000 ---p 001b8000 fd:00 33597608 /usr/lib64/libc-2.17.so
7f3fa6255000-7f3fa6259000 r--p 001b8000 fd:00 33597608 /usr/lib64/libc-2.17.so
7f3fa6259000-7f3fa625b000 rw-p 001bc000 fd:00 33597608 /usr/lib64/libc-2.17.so
7f3fa625b000-7f3fa6260000 rw-p 00000000 00:00 0
7f3fa6260000-7f3fa6275000 r-xp 00000000 fd:00 35340465 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f3fa6275000-7f3fa6474000 ---p 00015000 fd:00 35340465 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f3fa6474000-7f3fa6475000 r--p 00014000 fd:00 35340465 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f3fa6475000-7f3fa6476000 rw-p 00015000 fd:00 35340465 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f3fa6476000-7f3fa6577000 r-xp 00000000 fd:00 33827070 /usr/lib64/libm-2.17.so
7f3fa6577000-7f3fa6776000 ---p 00101000 fd:00 33827070 /usr/lib64/libm-2.17.so
7f3fa6776000-7f3fa6777000 r--p 00100000 fd:00 33827070 /usr/lib64/libm-2.17.so
7f3fa6777000-7f3fa6778000 rw-p 00101000 fd:00 33827070 /usr/lib64/libm-2.17.so
7f3fa6778000-7f3fa6861000 r-xp 00000000 fd:00 35340469 /usr/lib64/libstdc++.so.6.0.19
7f3fa6861000-7f3fa6a61000 ---p 000e9000 fd:00 35340469 /usr/lib64/libstdc++.so.6.0.19
7f3fa6a61000-7f3fa6a69000 r--p 000e9000 fd:00 35340469 /usr/lib64/libstdc++.so.6.0.19
7f3fa6a69000-7f3fa6a6b000 rw-p 000f1000 fd:00 35340469 /usr/lib64/libstdc++.so.6.0.19
7f3fa6a6b000-7f3fa6a80000 rw-p 00000000 00:00 0
7f3fa6a80000-7f3fa6aa1000 r-xp 00000000 fd:00 33597596 /usr/lib64/ld-2.17.so
7f3fa6c8f000-7f3fa6c94000 rw-p 00000000 00:00 0
7f3fa6c9f000-7f3fa6ca1000 rw-p 00000000 00:00 0
7f3fa6ca1000-7f3fa6ca2000 r--p 00021000 fd:00 33597596 /usr/lib64/ld-2.17.so
7f3fa6ca2000-7f3fa6ca3000 rw-p 00022000 fd:00 33597596 /usr/lib64/ld-2.17.so
7f3fa6ca3000-7f3fa6ca4000 rw-p 00000000 00:00 0
7ffc9f004000-7ffc9f025000 rw-p 00000000 00:00 0 [stack]
7ffc9f0e5000-7ffc9f0e7000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
已放弃(吐核)
[root@1]# addr2line -e a.out 0x400a74
/home/shiyuefeng/core/1/test1.cpp:35
addr2line 可以先大概的定位一下core的位置,当然这个不是重点!
接下来解释一波为什么会有double free?
1.首先可以确定double free的对象是char* buff, 因为其他的对象的内存都是在栈上申请的!
2.STL vector 在push 结构体的时候进行拷贝构造函数
补充拷贝构造函数进行测试
#include <vector>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
using namespace std;
class demo
{
public:
demo() :buffer(NULL)
{
buffer = new char[200];
strcpy(buffer, "hello world");
}
demo(const demo& src)
{
printf("copy assign function\r\n");
}
~demo()
{
if (buffer != NULL)
delete buffer;
buffer = NULL;
}
public:
char *buffer;
};
void fun()
{
demo a;
vector<demo> haha;
haha.push_back(a);
}
int main(int argc, char* argv[])
{
fun();
printf("执行完毕\r\n");
getchar();
return 0;
}
运行结果如下:
# ./a.out
copy assign function
执行完毕
很神奇,这个时候没有core了! 因为刚添加的拷贝构造函数的话 没有对成员变量进行复制,所以fun函数执行结束char* buff 就释放了一次!
默认的拷贝构造的话 会进行浅拷贝,直接将char*buff的指针给复制过去! 所以我们也加上去试试!
#include <vector>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
using namespace std;
class demo
{
public:
demo() :buffer(NULL)
{
buffer = new char[200];
strcpy(buffer, "hello world");
}
demo(const demo& src)
{
buffer = src.buffer;
printf("copy assign function\r\n");
}
~demo()
{
if (buffer != NULL)
delete buffer;
buffer = NULL;
}
public:
char *buffer;
};
void fun()
{
demo a;
vector<demo> haha;
haha.push_back(a);
}
int main(int argc, char* argv[])
{
fun();
printf("执行完毕\r\n");
getchar();
return 0;
}
运行结果:
copy assign function
*** Error in `./a.out': double free or corruption (!prev): 0x0000000001278010 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7c619)[0x7fc1e2029619]
./a.out[0x400b41]
./a.out[0x400a2c]
./a.out[0x400a74]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7fc1e1fcec05]
./a.out[0x400919]
这里说明一下: 当删除其中的元素 比如erase clear或pop_back的时候 都会进行析构!
说回那个指针的事情:很明显那个指针会引用了两次,一次是在demo a 这边,另外一个是在vector里面 所以就导致了一个double free的问题,所以要解决这个问题,必须进行深拷贝!
修改代码如下:
#include <vector>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
using namespace std;
class demo
{
public:
demo() :buffer(NULL)
{
buffer = new char[200];
strcpy(buffer, "hello world");
}
demo(const demo& src)
{
buffer = new char[200];
memcpy(buffer,src.buffer,strlen(src.buffer));
printf("copy assign function\r\n");
}
~demo()
{
printf("~demo\r\n");
if (buffer != NULL)
delete buffer;
buffer = NULL;
}
public:
char *buffer;
};
void fun()
{
demo a;
vector<demo> haha;
haha.push_back(a);
}
int main(int argc, char* argv[])
{
fun();
printf("执行完毕\r\n");
getchar();
return 0;
}