VC6/VC7自代STL实现的一个问题(vector与copy)

hxblvc 2006-11-14 03:12:31
发现VC6/VC7中自代STL实现的一个问题.
对vector的对象调用过copy函数之后,此对象在析构中释放内存时,会出错!!!

我对同样的代码在FreeBSD中,用g++编译后运行不会出错.


程序代码:
//test.cpp---------------------------------start
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>

int fun()
{
std::cout <<"in fun" <<std::endl;
std::string buf;
buf = "jdsf;lasjdf;ajs";
std::vector<unsigned char> v;
v.resize(buf.size());

//如果对v调用这个拷贝调用,函数退出时就会出错.
std::copy( buf.begin(), buf.end(), v.end());


std::cout <<"out fun" <<std::endl;
return 0;
}

int main()
{
fun();

return 0;
}
//test.cpp---------------------------------end

函数调用栈:
_free_dbg(void * 0x00441d40, int 1) line 1033 + 60 bytes
free(void * 0x00441d40) line 926 + 11 bytes
operator delete(void * 0x00441d40) line 7 + 9 bytes
std::allocator<unsigned char>::deallocate(void * 0x00441d40, unsigned int 15) line 64 + 38 bytes
std::vector<unsigned char,std::allocator<unsigned char> >::~vector<unsigned char,std::allocator<unsigned char> >() line 60
fun() line 37 + 19 bytes
main() line 44
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 77e889a5()

出错位置代码:
_free_dbg(void * 0x00441d40, int 1) line 1033 + 60 bytes
{
...
/* if we didn't already check entire heap, at least check this object */
if (!(_crtDbgFlag & _CRTDBG_CHECK_ALWAYS_DF))
{
/* check no-mans-land gaps */
if (!CheckBytes(pHead->gap, _bNoMansLandFill, nNoMansLandSize))
_RPT3(_CRT_ERROR, "DAMAGE: before %hs block (#%d) at 0x%08X.\n",
szBlockUseName[_BLOCK_TYPE(pHead->nBlockUse)],
pHead->lRequest,
(BYTE *) pbData(pHead));

if (!CheckBytes(pbData(pHead) + pHead->nDataSize, _bNoMansLandFill, nNoMansLandSize))
_RPT3(_CRT_ERROR, "DAMAGE: after %hs block (#%d) at 0x%08X.\n",
szBlockUseName[_BLOCK_TYPE(pHead->nBlockUse)],
pHead->lRequest,
XXX=> (BYTE *) pbData(pHead));
}
...
}


...全文
292 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
HappyTree 2006-11-14
  • 打赏
  • 举报
回复
这个可以类比到strcpy,在拷贝过去时访问那块内存后面的连续空间,越界但不会报告错误,只有下一次试图再次访问它时,要么出现数据错误(因为那块数据被破坏了),要么出现访问越界(因为你要析构那块未分配的空间)
hxblvc 2006-11-14
  • 打赏
  • 举报
回复
多谢HappyTree!!!


刚才看了一下工程中的代码,发现只有出错的部分是这样写的:
std::copy( buf.begin(), buf.end(), v.end());

基它部分用的是v.begin(),没问题.

晕,不知道自己当时怎么想的. 面壁去...

结贴了.
hxblvc 2006-11-14
  • 打赏
  • 举报
回复
啊,对.

可是,为什么在copy时不出错, 直到析构时才出错?
HappyTree 2006-11-14
  • 打赏
  • 举报
回复
补充一下,
std::copy( buf.begin(), buf.end(), back_inserter(v));
的效果是在最后添加,可能跟楼主的要求不太一致,以上这句相当于
v.resize(buf.size());
std::copy( buf.begin(), buf.end(), v.begin());
不过后面的方法效率应该会高一些,因为可以避免多次分配内存。
HappyTree 2006-11-14
  • 打赏
  • 举报
回复
注意,resize()这里只是保留了一定的空间,但并没有保留v.end()以后的空间,
可以改为:
std::copy( buf.begin(), buf.end(), back_inserter(v));

std::copy( buf.begin(), buf.end(), v.begin());
hxblvc 2006-11-14
  • 打赏
  • 举报
回复
std::vector<unsigned char> v;
v.resize(buf.size()); //这句就是用来分配内存的

//如果对v调用这个拷贝调用,函数退出时就会出错.
std::copy( buf.begin(), buf.end(), v.end());

楼上朋友, 请细心看一下代码.

再说了,如果v没有空间,copy进就出错了, 怎么会等到v析造时!!!
HappyTree 2006-11-14
  • 打赏
  • 举报
回复
我觉得是g++的问题,这里应该肯定会出错的,因为v的空间并没有申请
必须使用back_inserter来在最后添加新元素

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧