我用一个结构体保存了一个LPCTSTR的变量,我用new TCHAR[XX];赋给了哪个变量,然后我把这个结构体放到一个CList中,用完后我用delete 哪个我分配的内存时出错:Debug Error!
program:.......
DAMAGE:after normal block(#86) at xxxxxxxx.
我不知道那里出错了。
program:.......
DAMAGE:after normal block(#86) at xxxxxxxx.
我不知道那里出错了。
大概代码如下:
struct tagInfo
{
LPTSTR name;
DWORD id;
}Info,*pInfo;
CList<Info,&Info> infoList;
Info myInfo;
myInfo.id =1000;
infoList.AddTail(myInfo);
name=new TCHAR[lstrlen(myname)];//my name is a string which define in my project
...
// work out my work
POSITION pos=infoList.GetHeadPosition();
while(pos!=NULL)
{
POSITION nowpos=pos;
Info *thisInfo=&infoList.GetNext(pos);
if(thisInfo.id==1000)
{
TCHAR * tx=thiInfo.name;
thisInfo.name=NULL;
lstrcpy(toutname,tx);
delete[] tx;//error here!error here!error here!!!!
....
thisInfo.RemoveAt(nowpos);
}
}
原代码太长,写这段大概可以表达我的意思。我是不想自己写连表,clist的原代码部分有点看不懂,谁看的懂的给我解释一下AddTail函数时CList构造对象的过程,谢谢。
so you should use
delete tx;
Error again.
#include <afxtempl.h>
typedef struct xyz
{
double x;
double y;
double z;
}XYZ; char str[256];
CTypedPtrList <CPtrList, XYZ*> list;
//添加
XYZ *pxyz=new XYZ;
pxyz->x=0;
pxyz->y=1;
pxyz->z=2;
list.AddTail(pxyz);
pxyz=new XYZ;
pxyz->x=3;
pxyz->y=4;
pxyz->z=5;
list.AddTail(pxyz);
//遍历
POSITION pos;
pos=list.GetHeadPosition();
while(pos)
{
pxyz=list.GetNext(pos);
//可以修改其中的值
pxyz->x=5;
sprintf(str,"%f %f %f",pxyz->x,pxyz->y,pxyz->z);
}
//删除
pos=list.GetHeadPosition();
while(pos)
{
pxyz=list.GetNext(pos);
delete pxyz;
}
list.RemoveAll();
在不同模块中调用将产生问题。因为没有new过的指针,编译器比不知道分配了多大的内存空间,
所以无法用delete释放。例如:int *p = new int[20];
和int *q = new int;
则delete p; delete q;显然是释放不同大小的地址空间。
所以没有你的程序有问题。应该在同一模块中new和delete
不好意思,你讲错了!
1)不同模块调用delete,new是不安全的(但在同一编译器,同一运行库设置上是可行的,但建义是不要用,最好采用接口方式---谁份配谁释放的原则),这是没错的
2)int *p = new int[20];
和int *q = new int;
此时调用delete p,delete q,均不会出错(因为int时基本类型,不存在构造与析构问题)
而下面的会有问题:
CString *ps1=new CString[10];//会对每一个均调用一个CString()构造函数
CString *ps2=new CString;//只调用了一个CString()构造函数
而当析构时:当delete ps1;时就只会调用一个析构函数,而ps1[1~9]均不会调用析构函数,后果可想而知了,注意:delete ps1与delete []ps1;是释放同一个句柄
同样malloc,....均时如此(一般地,Xalloc,Xfree的相关函数时不调用构造与析构函数的)
如果你把ps1的值赋给其他的变量pstmp(不同模块中),编译器
怎么知道delete [] pstmp释放多少内存呢。
为什么说是不安全的?
内存分配是有纪录的,所以new 和 delete才能正常工作。
好好研究研究new和得delete吧
我自己写了一个list也是同样的错误。
我想我这样写你们可能更清楚一些:
struct tagInfo
{
LPTSTR Infoname;
...
}Info;
Info *theInfo=new Info;
theInfo->Infoname=new TCHAR[lstrlen(myname)];
delete[] theInfo->Infoname; //这时就出错了
还有什么不清楚需要我说的详细一点的?
把LPTSTR改为CString 就没问题了。
我对CString 不信任,又不会用STL也不想自己写一个字符串处理类。
typedef struct
{
LPTSTR Infoname;
} Info;
char myname[]="wangjin";
Info * theInfo=new Info;
theInfo->Infoname=new TCHAR[lstrlen(myname)];
delete [] theInfo->Infoname;
delete theInfo;
可能你没懂我的意思:
我说delete ps1;少调用了九个析构函数(要使用delete []ps1其它九个对象)
但delete []基本类型时与delete 相同(如int,char ...)---其不存在析构与构造
还有delete []与delete与内存长度无关(它们的不同是编译器实现的,而真正的释放内存却是操作系统作的(重载除外),操作系统只认识句柄,他们传入的也是同一相句柄,所以操作系统作的是同样的事只是编译器编译的析构不一样而已(对于没有析构的基本类型,所以是一样的)
>>struct tagInfo
>>{
>>LPTSTR Infoname;
>>...
>>}Info;
>>Info *theInfo=new Info;
>>theInfo->Infoname=new TCHAR[lstrlen(myname)];
>>delete[] theInfo->Infoname; //这时就出错了不可能吧
你的代码是有问题。
struct tagInfo
{
LPTSTR name;
DWORD id;
}Info,*pInfo;
CList<Info,&Info> infoList;
Info myInfo;
myInfo.id =1000;
infoList.AddTail(myInfo);
name=new TCHAR[lstrlen(myname)];//my name is a string which define in my project
...
/////////////////这儿分配的长度为myname的长度,而且没包括末尾的NULL字符。
// work out my work
POSITION pos=infoList.GetHeadPosition();
while(pos!=NULL)
{
POSITION nowpos=pos;
Info *thisInfo=&infoList.GetNext(pos);
if(thisInfo.id==1000)
{
TCHAR * tx=thiInfo.name;
thisInfo.name=NULL;
lstrcpy(toutname,tx);
/////////////这儿拷贝字符串,拷贝长度为(tx长度+1),不一定小于myname的长度,极可能越界。
delete[] tx;//error here!error here!error here!!!!
//////////////////////所以释放内存时可能出错。
....
thisInfo.RemoveAt(nowpos);
}
}
我以为这是小问题,没想到我在这儿浪费了好几天的时间,谢谢谢谢!!!