删除字符串时堆损坏
这是我的代码:
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;
}
第一行读取字符串的长度。
第二行创建一个新的字符数组(c-string),其长度为字符串
第三行读取字符串(从文件中读取)
第 4 行在末尾添加 NULL。
第 5 行从 c 字符串中创建一个 std::string。
第 6 行删除 c 字符串(HEAP CORRUPTION HAPPENS HERE)
第 7 行返回字符串,但由于错误,它永远不会到达这一点。
在第 6 行,我收到堆损坏错误: CRT 检测到应用程序在堆缓冲区末尾后写入内存。
我的问题可能很明显,但为什么我会出现堆损坏?当我创建 std::string 时,它应该复制该字符串,并且我应该可以安全地删除 c 字符串。
目前,我怀疑 std::string 在删除 c 字符串后试图访问它。
有什么想法吗?
Here is my code:
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;
}
The first line reads the length of the string.
The second line creates a new char array (c-string) with the string length
The third line reads the string (its reading it from a file)
The 4th line adds a NULL to the end.
The 5th line creates an std::string out of the c-string.
The 6th line deletes the c-string (HEAP CORRUPTION HAPPENS HERE)
The 7th line returns the string, but it never reaches this point because of an error.
On the 6th line I get a heap corruption error:
CRT detected that the application wrote to memory after end of heap buffer.
My question may be obvious, but why am I getting a heap corruption? When I create an std::string, it should copy the string, and I should be safe to delete the c-string.
Currently, I'm suspecting that std::string is trying to access the c-string after I delete it.
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您正在访问超过字符串的保留字节。您保留了
strLen
字符,但在字符strLen
处放置了\0
。从 0 开始计算 C 数组,字符strLen
位于位置strLen + 1
,因此您将一个值放在字符串的保留空间之外。您应该在main
的第二行中保留strLen + 1
以使代码正常工作。You're accessing past the reserved bytes for your string. You reserved
strLen
characters, but put a\0
at the characterstrLen
. Counting as C arrays from 0, characterstrLen
is at positionstrLen + 1
, so you're putting a value outside the reserved space for the string. You should reservestrLen + 1
in the second line of yourmain
for your code to work.更改:
至:
Change:
to:
int strLen = Read()
可能仅返回非空终止字符串的长度,并且当您尝试写入\0< /code> byte 到字符串,你会遇到缓冲区溢出问题。
您应该检查
strLen
是什么,很可能您必须像这样分配:或者使用
std::string(const char *, size_t n)
的重载构造函数像这样:int strLen = Read<int>()
probably only returns the length of a non-null-terminated string, and when you try to write the\0
byte to the string, you run into buffer overflow problems.You should check what
strLen
is, and most likely you either have to allocate like this:Or use the overloaded constructor of
std::string(const char *, size_t n)
like this:由于数组在 C++ 中是从 0 索引的,因此当您创建一个大小为
strLen
的数组,然后在位置strLen
处放置一个 0 时,您将在您分配的数组。Since arrays are 0-indexed in c++, when you create an array of size
strLen
and then place a 0 at positionstrLen
, you are writing that zero one after the end of the array you allocated.到目前为止有很多建议,但没有一个解决异常安全问题:如何消除潜在的内存泄漏?
有两种方法可以避免使用 new 进行分配(从而避免内存泄漏)。第一个非常简单,使用称为 VLA 的编译器扩展来表示可变长度数组:
另一个符合标准:
string
有一个可以访问的内部缓冲区(感谢 GMan,< code>data 不是正确的访问方法)我确实相信最后一个版本要好得多。不再涉及任何复制:)
Many advices so far, but none which address the exception safety issue: how do you get rid of that potential memory leak ?
There are two ways to avoid allocating with
new
(and thus facing a memory leak). The first is extremely simply and makes use of a compiler extension known as VLA for Variable Length Array:The other is compliant with the standard:
string
has an internal buffer which you can access (thanks to GMan,data
is not the right access method)I do believe that the last version is MUCH better. There is no longer any copying involved :)
将 NUL 从您分配的空间末尾写掉。
如果strLen是10,那么你分配10个字符的空间,读取10个字符,并将这个NUL写入位置11。哎呀
Writes the NUL off the end of the space you have allocated.
If strLen is 10, then you allocate space for 10 characters, read 10 characters, and write this NUL in position 11. Ooops