+ -
当前位置:首页 → 问答吧 → <Linux,G++> 标准库Bug? 析构函数中删除动态数组时出错.

<Linux,G++> 标准库Bug? 析构函数中删除动态数组时出错.

时间:2010-09-03

来源:互联网

本帖最后由 wonderbeyond 于 2010-09-03 12:41 编辑

经过苦苦探寻, 我发现我的程序错误出在智能指针的析构函数的调用中.
那是在程序结束时, 智能指针的引用计数降为0, 所以释放该智能指针, 智能指针的析构函数的任务是:
释放其持有的 char 型动态分配的内存. 可错误就出在智能指针释放内存时. 为了便于研究, 我把相关部分单独抽出来, 作为一个示例程序:
/////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <cstring>

using namespace std;

class SmartPtr
{
public:
    SmartPtr(char* p) : buf(p), use(1) {}
    ~SmartPtr() { std::cout << "~SmartPtr() called\n"; delete [] buf; }
    char* buf;
    int use;
};


int main(int argc, char** argv)
{
    SmartPtr ptr(new char(100));
    memcpy(ptr.buf, argv[1], strlen(argv[1]));
    cout << "got: " << ptr.buf << endl;
    return 0;
}
/////////////////////////////////////////////////////////
$g++ test.cc -o test
当程序结束时, ptr超出作用域, 自然就会调用其析构函数释放我们分配的size为100的内存, 但如果
argv[1]的长度大于13时, 程序结束时会产生一大堆错误输出.
下面是执行 ./test "12345678901234" 的输出:

got: 12345678901234
~SmartPtr() called
*** glibc detected *** ./a.out: free(): invalid next size (fast): 0x08981008 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(+0x6b591)[0x246591]
/lib/tls/i686/cmov/libc.so.6(+0x6cde[0x247de8]
/lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0x24aecd]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xe77741]
/usr/lib/libstdc++.so.6(_ZdaPv+0x1d)[0xe7779d]
./a.out[0x80489ac]
./a.out[0x80488e1]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0x1f1bd6]
./a.out[0x80487b1]
======= Memory map: ========
001be000-001d9000 r-xp 00000000 08:02 1179674    /lib/ld-2.11.1.so
001d9000-001da000 r--p 0001a000 08:02 1179674    /lib/ld-2.11.1.so
001da000-001db000 rw-p 0001b000 08:02 1179674    /lib/ld-2.11.1.so
001db000-0032e000 r-xp 00000000 08:02 1311275    /lib/tls/i686/cmov/libc-2.11.1.so
0032e000-0032f000 ---p 00153000 08:02 1311275    /lib/tls/i686/cmov/libc-2.11.1.so
0032f000-00331000 r--p 00153000 08:02 1311275    /lib/tls/i686/cmov/libc-2.11.1.so
00331000-00332000 rw-p 00155000 08:02 1311275    /lib/tls/i686/cmov/libc-2.11.1.so
00332000-00335000 rw-p 00000000 00:00 0
0037c000-0037d000 r-xp 00000000 00:00 0          [vdso]
00a5d000-00a81000 r-xp 00000000 08:02 1311283    /lib/tls/i686/cmov/libm-2.11.1.so
00a81000-00a82000 r--p 00023000 08:02 1311283    /lib/tls/i686/cmov/libm-2.11.1.so
00a82000-00a83000 rw-p 00024000 08:02 1311283    /lib/tls/i686/cmov/libm-2.11.1.so
00c78000-00c95000 r-xp 00000000 08:02 1179732    /lib/libgcc_s.so.1
00c95000-00c96000 r--p 0001c000 08:02 1179732    /lib/libgcc_s.so.1
00c96000-00c97000 rw-p 0001d000 08:02 1179732    /lib/libgcc_s.so.1
00dbc000-00ea5000 r-xp 00000000 08:02 1052341    /usr/lib/libstdc++.so.6.0.13
00ea5000-00ea6000 ---p 000e9000 08:02 1052341    /usr/lib/libstdc++.so.6.0.13
00ea6000-00eaa000 r--p 000e9000 08:02 1052341    /usr/lib/libstdc++.so.6.0.13
00eaa000-00eab000 rw-p 000ed000 08:02 1052341    /usr/lib/libstdc++.so.6.0.13
00eab000-00eb2000 rw-p 00000000 00:00 0
08048000-08049000 r-xp 00000000 08:03 403110     /home/wonder/lab/a.out
08049000-0804a000 r--p 00000000 08:03 403110     /home/wonder/lab/a.out
0804a000-0804b000 rw-p 00001000 08:03 403110     /home/wonder/lab/a.out
08981000-089a2000 rw-p 00000000 00:00 0          [heap]
b7700000-b7721000 rw-p 00000000 00:00 0
b7721000-b7800000 ---p 00000000 00:00 0
b78ea000-b78ec000 rw-p 00000000 00:00 0
b78fc000-b78ff000 rw-p 00000000 00:00 0
bff44000-bff59000 rw-p 00000000 00:00 0          [stack]
已放弃

作者: wonderbeyond   发布时间: 2010-09-03

本帖最后由 wonderbeyond 于 2010-09-03 12:14 编辑

我现在有点怀疑是标准库Bug了...

作者: wonderbeyond   发布时间: 2010-09-03

这个程序是否free(): invalid next size,完全是随机的,和13没有关系。
错误的原因是SmartPtr ptr(new char(100));应该是new char[100]
分配的空间根本不够用来存储argv[1]的字符串,所以free的时候就会出错。

作者: insnowind   发布时间: 2010-09-03



QUOTE:
这个程序是否free(): invalid next size,完全是随机的,和13没有关系。
错误的原因是SmartPtr ptr(new ch ...
insnowind 发表于 2010-09-03 12:51



大哥, 看了你的回复,我突然抓狂了, 原来是我把创建动态数组的语法搞错了.....
惭愧!

作者: wonderbeyond   发布时间: 2010-09-03

相关阅读 更多