C++ 删除字符串时堆损坏
这是我的密码:C++ 删除字符串时堆损坏,c++,string,stl,heap,cstring,C++,String,Stl,Heap,Cstring,这是我的密码: std::string readString() { int strLen = Read<int>(); char* rawString = new char[strLen]; Read(rawString, strLen); rawString[strLen] = '\0'; std::string retVal(rawString); delete [] rawString; return re
std::string readString()
{
int strLen = Read<int>();
char* rawString = new char[strLen];
Read(rawString, strLen);
rawString[strLen] = '\0';
std::string retVal(rawString);
delete [] rawString;
return retVal;
}
std::string readString()
{
int strLen=Read();
char*rawString=新字符[strLen];
读取(原始字符串,strLen);
原始字符串[strLen]='\0';
std::string retVal(rawString);
删除[]原始字符串;
返回返回;
}
第一行读取字符串的长度。第二行创建一个字符串长度为
第三行读取字符串(从文件中读取)
第四行在末尾添加一个空值。
第5行从c字符串中创建一个std::字符串。
第6行删除c字符串(此处发生堆损坏)
第7行返回字符串,但由于错误,它从未到达这一点 在第6行,我得到一个堆损坏错误: CRT检测到应用程序在堆缓冲区结束后写入内存 我的问题可能很明显,但为什么我会得到一堆腐败?当我创建一个std::string时,它应该复制这个字符串,我应该可以安全地删除这个c字符串 目前,我怀疑std::string在删除c字符串后试图访问它 有什么想法吗
int strLen=Read()
可能只返回以非空结尾的字符串的长度,当您尝试将\0
字节写入字符串时,会遇到缓冲区溢出问题
您应该检查strLen是什么,很可能您必须这样分配:
char *rawString = new char[strlen+1];
std::string retVal(rawString, strlen);
或者像这样使用std::string(const char*,size\t n)
的重载构造函数:
char *rawString = new char[strlen+1];
std::string retVal(rawString, strlen);
您正在访问字符串的保留字节。您保留了
strLen
字符,但在字符strLen
处放置了一个\0
。从0开始作为C数组计数,字符strLen
位于位置strLen+1
,因此将一个值放在字符串的保留空间之外。您应该在main
的第二行中保留strLen+1
,以便代码正常工作。更改:
char* rawString = new char[strLen];
致:
由于数组在C++中是0索引的,当你创建一个大小为<代码> StLLUN <代码>的数组,然后在位置<代码> StLLUN < /> >中放置一个0,在你所分配的数组的末尾,你就写了0个。
rawString[strLen] = '\0';
将NUL从已分配空间的末尾写入
rawString[strLen] = '\0';
如果strLen为10,则为10个字符分配空间,读取10个字符,然后将该NUL写入位置11。Ooops到目前为止有很多建议,但没有一个能解决异常安全问题:如何消除潜在的内存泄漏 有两种方法可以避免使用
new
进行分配(从而避免内存泄漏)。第一种方法非常简单,使用了一种称为VLA的编译器扩展,用于可变长度数组:
std::string readString()
{
int strLen = Read<int>();
char rawString[strLen+1]; // VLA: the length is determined at runtime
// but the array is nonetheless on the stack
Read(rawString, strLen);
rawString[strLen] = '\0';
std::string retVal(rawString);
return retVal;
}
我相信最后一个版本要好得多。不再涉及任何复制:)您的代码中有
delete[]
,因此您的代码是错误的。使用std::vector
或其他什么,甚至直接读入字符串。@GMan:在我发布之前,我甚至没有看到你的评论:p它还简化了代码,真是不可思议……谢谢。真不敢相信我竟然忽略了那样的事情。我用C++已经有一段时间了:谢谢所有在这上面发布帮助的人!前者是非标准C++,实际上是非标准C++。第二个只允许const访问:要读入向量
或保留字符串并读入&retVal[0]
,这会产生一个连续的缓冲区。哦,你说的“非常简单”。)@GMan:废话,我以为有两种版本的数据。我确实认为前者是非标准的,但我确实认为它是一个编译器扩展(而且是一个很好的扩展…)