我正在尝试构建一个处理String运算符的类。但是,由于没有令人信服的理由,它有时会在delete []运算符期间崩溃。我使用strsafe库来执行所有内部字符串操作。
// QString的
LPTSTR 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]:为RtlFreeHeap指定的无效地址(003C0000,003C46A8)
或
HEAP [StringTest.exe]:003C4750处的堆块修改为003C475C,请求大小超过4
答案 0 :(得分:1)
构造函数不会将m_string初始化为NULL(根据您自己的评论)。这导致随机的Free()失败。
正如selbie所说,此代码中还存在其他错误和效率低下的问题。例如,替换始终重新分配,即使从已分配的+ =调用也是如此。并且在Replace和Alloc中都添加了1,表明您不清楚哪些函数采用包含终结符的值,哪些函数不包含终结符。
除非这是一个学习或家庭作业练习,否则我强烈建议不要编写自己的字符串类 - 这将比你使用std :: string(或ATL ::)更加努力地获得一些合理有效的工作。 CString如果你愿意的话。)
马丁
答案 1 :(得分:1)
另一个答案:
我的通灵能力告诉我,如果QString没有复制构造函数,那么当ToStr()在堆栈上返回QString的“副本”时,可能会发生不好的事情。
答案 2 :(得分:0)
我看到很多错误。
对于初学者,如果将0传递给ToStr函数,则只会分配一个内存字符串来保存字符串“0”,这是两个字节('0'+ null char)。此外,如果将负整数传递给此函数,则会发生其他不良事件。你最好只分配超过你需要的东西而不试图计算“确切”的大小。
int size = sizeof(_in) * 4 + 1;
你的strcpy都没有(即使使用StringCch功能)让我感觉良好。
我建议分配2倍所需的“大小”,然后通过调试仔细研究缓冲区和m_string的内存地址,如果strcpy超出“size-1”字节(不包括null终止字符)。 / p>
答案 3 :(得分:0)
您的整个分配和自由算法是基于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分之一的错误(fencepost错误),其中整数的大小总是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++;
}
}
<\ n>在Replace()中,Alloc()增加2个字符。
size_t size = strlength(src)+1;
应该是
size_t size = strlength(src);
如果你需要一个额外的字符:: StringCchCopy(m_string,size,src);在那里放大小+ 1。或者更改您的Alloc,以便它准确分配您要求的字符数(如名称所示)。