大家帮忙看一个内存出错的问题,搞的我很头疼,谢谢!!!!

rabbit729 2008-12-01 02:08:54
小弟想用模板实现一个线性表,代码如下,可是模板的赋值构造函数好像有问题,下面这段代码运行时总是出错,请大家帮忙看看,一块分析一下,谢谢!!!我的编译环境时VS2005
/**************头文件******************/

/**
* @file ListSqu.h
* @author Wang Liuqiang
* @version 1.0
* @date 2008-11-30
* @brief 该类实现了线性表的顺序表示
*/

#ifndef LISTSQU_H_
#define LISTSQU_H_

#include <assert.h>
#include <iostream>
using namespace std;

#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10

#define SQUSUCCEED 0
#define SQUERROR -1
#define SQUOVERFLOW -2

template <class T>
class ListSqu
{
public:
/*
*name 构造函数/析构函数
*@{
*/
ListSqu();
~ListSqu();

ListSqu(const ListSqu<T>& ls);
ListSqu<T>& operator=(const ListSqu<T>& ls);
/** @}*/ //构造函数/析构函数

public:
/*
* 清空顺序表
* @return 返回函数执行结果:
* -0 表示执行成功
* -1 表示执行出错
*/
int ClearList();

/*
* 判断顺序表是否为空
* @return 返回函数执行结果:
* -true 表示顺序表为空
* -false 表示顺序表不为空
*/
bool IsEmpty();

/*
* 返回顺序表中元素个数
* @return 返回顺序表中元素个数
*/
int Length();

/*
* 返回顺序表中第i个位置的元素
* @param[in] i 需要获取元素的位置
* @param[out] e 顺序表中第i个位置的元素值
* @return 返回函数执行结果
* -SQUSUCCEED 表示函数执行成功
* -SQUERROR 表示函数执行失败
* @note C++中数组的下标是从0开始,因此第i个位置的元素应该取下标为i-1的元素
*/
int GetItem(int i, T& e);

/*
* 在顺序表的第i个位置之前插入元素
* @param[in] 元素的插入位置
* @param[in] 插入元素值
* @return 返回函数的执行结果
* -SQUSUCCEED 表示函数执行成功
* -SQUERROR 表示函数执行失败
*/
int InsertItem(int i, T& e);

/*
* 删除顺序表中第i个位置的元素
* @param[in] i 待删除元素位置
* @param[out] e 删除元素的值
* @return 返回函数的执行结果
* -SQUSUCCEED 表示函数执行成功
* -SQUERROR 表示函数执行失败
*/
int DeleteItem(int i, T& e);

/*
* 显示顺序表中元素
* @return 返回函数的执行结果
* -SQUSUCCEED 表示函数执行成功
* -SQUERROR 表示函数执行失败
*/
int Show(); // 输出表中元素

private:
T* items;
int length;
int listsize;
};

template <class T>
ListSqu<T>::ListSqu()
{
items = new T[LIST_INIT_SIZE];
assert(items);
length = 0;
listsize = LIST_INIT_SIZE;
}

template <class T>
ListSqu<T>::~ListSqu()
{
if (items != NULL)
{
delete[] items;
items = NULL;
}
}

template <class T>
ListSqu<T>::ListSqu(const ListSqu<T>& ls)
{
length = ls.length;
listsize = ls.listsize;

items = new T[listsize + 1];
memcpy(items, ls.items, _msize(ls.items));
}

template <class T>
ListSqu<T>& ListSqu<T>::operator=(const ListSqu<T>& ls)
{
if( this == &ls )
return *this;

delete[] items;
items = NULL;

length = ls.length;
listsize = ls.listsize;

items = new T[length + 1];
memcpy(items, ls.items, _msize(ls.items));
return *this;
}

template <class T>
int ListSqu<T>::ClearList()
{
length = 0;
return SQUSUCCEED;
}

template <class T>
bool ListSqu<T>::IsEmpty()
{
return length == 0;
}

template <class T>
int ListSqu<T>::GetItem(int i, T& e)
{
if ( (i < 1) || ( i > length ))
{
cout<<"所给位置超出位置索引!"<<endl;
return SQUERROR;
}
else
{
e = items[i -1];
return SQUSUCCEED;
}
}

template <class T>
int ListSqu<T>::InsertItem(int i, T& e)
{
if ( i < 1 || i > length + 1)
{
cout<<"所给位置出错!"<<endl;
return SQUERROR;
}
else
{
if (length >= listsize)
{
T* pNew = new T[LISTINCREMENT];
memcpy(pNew, items, _msize(items));
items = pNew;

if (items == NULL)
{
cout<<"申请内存空间失败!"<<endl;
return SQUOVERFLOW;
}
listsize += LISTINCREMENT;
}

for(int k = length; k >= i - 1; k--)
{
items[k+1] = items[k];
}

items[i-1] = e;
length++;

return SQUSUCCEED;
}
}

template <class T>
int ListSqu<T>::DeleteItem(int i, T& e)
{
if ( i < 1 || i > length )
{
cout<<"所给删除位置出错!"<<endl;
return SQUERROR;
}

e = items[i-1];

for (i = i -1; i < length; i++)
{
items[i] = items[i + 1];
}
length--;
return SQUSUCCEED;
}

template <class T>
int ListSqu<T>::Show()
{
for (int i = 0; i < length; i++)
{
cout<<items[i]<<endl;
}
return SQUSUCCEED;
}
#endif
/************main.cpp*****************/

#include "ListSqu.h"

void main()
{
ListSqu<int> listtest;
for (int i = 0; i < 10; i++)
{
listtest.InsertItem(i+1, i);
}
listtest.Show();

ListSqu<int> listtest1;
listtest1 = listtest;

//ListSqu<int> listtest1 = listtest; // 将上面两句使用这句代码替换,没有错误
listtest1.Show();
}
...全文
120 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
taifeng123 2008-12-01
  • 打赏
  • 举报
回复
在vc++6.0中:我把你的m_size改为sizeof后就没有问题了,但是复制的不是数据,是地址,说明了你的m_size没有定义。
ListSqu <int> listtest1;
listtest1 = listtest;
你上面的这个是因为你用了const,listtest1的初值已经设置了,不能在把listtest赋给listtest1.
ListSqu <int> listtest1 = listtest;//这个你开始定义的时候就赋值为listtest.
请问楼主 memcpy中的这个m_size是不是和strlen有一样的功能。
wudeshou82666 2008-12-01
  • 打赏
  • 举报
回复
new 出来的内存块,会在前后多一些字节来存储这块内存的信息.如果你申请的内存不够,造成写越界,改变了这些信息,在你释放这块内存的时候就会报错.....
rabbit729 2008-12-01
  • 打赏
  • 举报
回复
这种内存越界造成的运行出错以前在那看到过一句话:“内存越界造成的释放时出错的情况在debug下能够出错,在release下就不会出错”可我这个程序在Debug和Release下都出错,?????
coanororc 2008-12-01
  • 打赏
  • 举报
回复
之所以在析构函数中出错,是因为在析构函数中释放内存的时候,访问到了越界的内存。这个问题我也遇到过,一些内存非法操作在运行的时候是不会出错的,但当你释放这些内存的时候就会崩掉程序,原因是访问到了那些根本不在堆上分配的内存,而程序运行期间,它可以访问栈上的内存,但当你free或者delete的时候,那些内存是必须要在堆上已经分配过的。我猜想LZ的代码可能就是这个原因所致:运行期跑的是stack上的内存,而析构的时候,释放的(free/delete)却是heap上的内存,但却是不存在的或者越界区的内存。
rabbit729 2008-12-01
  • 打赏
  • 举报
回复
我找到原因了,
template <class T>
ListSqu <T>& ListSqu <T>::operator=(const ListSqu <T>& ls)
{
if( this == &ls )
return *this;

delete[] items;
items = NULL;

length = ls.length;
listsize = ls.listsize;

items = new T[length + 1]; // 修改为items = new T[length + 150];
memcpy(items, ls.items, _msize(ls.items));
return *this;
}

items = new T[length + 1];
这里应该是
items = new T[listsize + 1];
listsize是我在类的构造函数中初始化分配的内存数,而length是当前线性表中存放的元素个数,这里用length+1分配内存,而在memcpy(items, ls.items, _msize(ls.items)); 又将sizeof(T)*listsize长的字节拷贝给items该处放声越界了,我比较纳闷的就是越界为什么不会在程序执行到该处时出错,而是在析构函数时出错,这个帖暂时先不解,大家也看一下吸取一下教训吧
rabbit729 2008-12-01
  • 打赏
  • 举报
回复
我把代码做如下修改问题就解决了,可是不明白为什么?谢谢!!!
template <class T>
ListSqu <T>& ListSqu <T>::operator=(const ListSqu <T>& ls)
{
if( this == &ls )
return *this;

delete[] items;
items = NULL;

length = ls.length;
listsize = ls.listsize;

items = new T[length + 1]; // 修改为items = new T[length + 150];
memcpy(items, ls.items, _msize(ls.items));
return *this;
}

shell8232565 2008-12-01
  • 打赏
  • 举报
回复
ListSqu(const ListSqu <T>& ls);
ListSqu <T>& operator=(const ListSqu <T>& ls);

没有发现你定义成const 了吗?声明的同时进行初始化啊

64,677

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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