动态分配LPTSTR (TCHAR*)和delete[]操作符的不稳定行为
Unstable behavior of dynamically allocated LPTSTR (TCHAR*) and delete[] operator?
我试图构建一个处理String操作符的类。然而,由于没有令人信服的原因,它有时会在delete[]操作期间崩溃。我使用strsafe库来完成所有的内部字符串操作。
//qstringLPTSTR m_string;
void QString::operator +=(const QString &_in) //Concat m_string with _in.m_string
{
size_t size = strlength(m_string) + strlength(_in.m_string) +1; //new size
LPTSTR buffer = new TCHAR[size]; //alloc buffer
::StringCchCopy(buffer,strlength(m_string)+1,m_string); //copy current m_string to buffer
::StringCchCat(buffer, size, _in.m_string); //concat buffer with the input
Replace(buffer); //replace this object with m_string
delete[] buffer; //dealloc
}
void QString::Replace(LPCTSTR src) //replace m_string with src
{
size_t size = strlength(src)+1; //new size
Alloc(size);
::StringCchCopy(m_string,size,src); //copy src to m_string
}
void QString::Alloc(size_t size) //Dynamic allocation
{
if(m_string != NULL) Free();
m_string = new TCHAR[size+1];
}
void QString::Free() //Free m_string
{
delete[] m_string; //Sometime crashes here
m_string = NULL;
}
QString ToStr(int _in) //Convert Integer to qstring
{
int size = 1;
int f = _in;
while(f > 0)
{
f /=10;
size++;
}
TCHAR* buf = new TCHAR[size];
for(int i = 0; i < size; i++) buf[i] = (TCHAR)TEXT("");
QString result(L"undef");
if(::_itow_s(_in,buf,size,10) == 0) //No error code = ok
{
result = buf;
}
delete[] buf;
return result;
}
//示例1:不崩溃
int ::WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd)
{
QString a(L"");
a += L"TEST";
a += ToStr(1000);
::MessageBox(0,a.GetStr(),L"NOTHING",MB_OK);
return 0;
}
//示例2:打印奇怪的字符加上一些当前字符(Unicode问题?)
int ::WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd)
{
QString a(L"");
a += L"TESTTESTESTEST";
a += ToStr(1000);
::MessageBox(0,a.GetStr(),L"NOTHING",MB_OK);
return 0;
}
//示例3:加载时崩溃
int ::WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd)
{
QString a(L"");
a += L"TESTTESTESTEST";
a += ToStr(1000);
a += L"TESTESTEST";
a += ToStr(100);
::MessageBox(0,a.GetStr(),L"NOTHING",MB_OK);
return 0;
}
在Free()操作delete[]操作符时崩溃。错误为
HEAP[StringTest.exe]: Invalid Address specified to RtlFreeHeap(003C0000, 003C46A8)
或
HEAP[StringTest.exe]:堆块在003C4750修改在003C475C超过请求的大小4
你的构造函数没有初始化m_string为NULL(根据你自己上面的评论)。这将导致随机的Free()失败。
正如selbie所指出的,这段代码中还有其他bug和低效率。例如,Replace总是重新分配,即使从已经分配的+=调用也是如此。并且您在Replace和Alloc中都添加了1,这表明您不清楚哪些函数的值包含终止符,哪些不包含终止符。
除非这是一个学习或家庭作业练习,否则我强烈建议不要编写自己的字符串类-与使用std::string(或者ATL::CString,如果您喜欢)相比,它将花费您更多的工作来获得合理和高效的内容。
Martyn
另一个答案:
我的灵力告诉我,如果QString没有复制构造函数,那么当ToStr()返回堆栈上QString的"副本"时,可能会发生不好的事情。
我看到很多bug。
对于初学者来说,如果你将0传递给ToStr函数,你将只分配一个字节的内存来保存字符串"0",这是两个字节('0' + null char)。此外,如果向这个函数传递一个负整数,还会发生其他不好的事情。你最好分配比你需要的更多,而不要试图计算"确切"的大小。
int size = sizeof(_in) * 4 + 1;
没有一个你的字符串(即使使用stringch函数)让我感觉很好。
我建议分配2倍的"大小"你需要,然后仔细研究缓冲区和m_string的内存地址通过调试,如果strcpy超过"size-1"字节(不包括null终止字符)。
您的整个分配和自由算法是基于m_string已初始化为NULL的事实。你在构造函数中这样做了吗(我在这里没有看到)?
顺便说一下,可能与名为Alloc()的CRT库函数有冲突。http://msdn.microsoft.com/en-us/library/dd492420%28VS.100%29.aspx
计算整型字符串长度的算法不正确。从size=1开始,应该从size=0开始。此外,您还需要处理特殊情况,其中0==f: 0绝对是一个数字,并且占用1个字符。你有一个偏离1的错误(栅栏错误),整数的大小总是太大1。
QString ToStr(int _in) //Convert Integer to qstring
{
int size = 0;
int f = _in;
if (0==f) {
size=1;
} else {
while(f > 0) {
f /=10;
size++;
}
}
在Replace()中,你Alloc() 2个额外的字符。
size_t size = strlength(src)+1;
应为
size_t size = strlength(src);
,如果你需要一个额外的字符::StringCchCopy(m_string,size,src);在这里输入size+1。或者更改您的Alloc,以便它分配您所要求的字符数量(如名称所示)。
- Arduino Nano:A4988 使用串行输入时通过定时器进行步进控制不稳定
- 我不知道为什么复制构造函数的调用在 c++ 中不稳定
- ArUco姿态估计中的不稳定值
- 当我使用 fstream 与 for 一起使用时值不稳定,C++
- 不稳定的C :每行适应性变化多变量初始化
- 加入向量的所有线程后,程序不稳定,而不是退出
- clEnqueueWriteImage 在执行时间上不稳定
- 不稳定:如何设置初始化器列表和函数参数的凹痕
- 图形场景中的方位角公式计算会产生不稳定的结果
- 配置不稳定以添加括号
- 向量中的项目的指针不稳定
- C++ 今天的多线程,C++ 11 的不稳定情况 - 书籍建议
- 分析计时不稳定
- 格式化构造构件成员初始化,不稳定
- 可以不稳定和/或通用的GUI划分字符串文字
- C++11 中不稳定 - 随访
- 为什么这个模拟中的摩擦力会使物体的行为不稳定
- 构建 Z3 不稳定分支时出错
- C++中不稳定的类成员
- 动态分配LPTSTR (TCHAR*)和delete[]操作符的不稳定行为