删除字符串时堆损坏

发布于 2024-10-03 02:09:11 字数 695 浏览 11 评论 0原文

这是我的代码:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

獨角戲 2024-10-10 02:09:11

您正在访问超过字符串的保留字节。您保留了 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 character strLen. Counting as C arrays from 0, character strLen is at position strLen + 1, so you're putting a value outside the reserved space for the string. You should reserve strLen + 1 in the second line of your main for your code to work.

画离情绘悲伤 2024-10-10 02:09:11

更改:

char* rawString = new char[strLen];

至:

char* rawString = new char[strLen + 1];

Change:

char* rawString = new char[strLen];

to:

char* rawString = new char[strLen + 1];
高速公鹿 2024-10-10 02:09:11

int strLen = Read()可能仅返回非空终止字符串的长度,并且当您尝试写入 \0< /code> byte 到字符串,你会遇到缓冲区溢出问题。

您应该检查 strLen 是什么,很可能您必须像这样分配:

char *rawString = new char[strlen+1];

或者使用 std::string(const char *, size_t n) 的重载构造函数像这样:

std::string retVal(rawString, strlen);

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:

char *rawString = new char[strlen+1];

Or use the overloaded constructor of std::string(const char *, size_t n) like this:

std::string retVal(rawString, strlen);
记忆消瘦 2024-10-10 02:09:11

由于数组在 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 position strLen, you are writing that zero one after the end of the array you allocated.

鼻尖触碰 2024-10-10 02:09:11

到目前为止有很多建议,但没有一个解决异常安全问题:如何消除潜在的内存泄漏?

有两种方法可以避免使用 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;
}

另一个符合标准:string 有一个可以访问的内部缓冲区(感谢 GMan,< code>data 不是正确的访问方法)

std::string readString()
{
  int strLen = Read<int>();

  std::string retVal(strLen, '\0'); // no need to allocate extra space

  Read(&retVal[0], strLen);      // &retVal[0] gives access to the buffer

  return retVal;
}

我确实相信最后一个版本要好得多。不再涉及任何复制:)

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:

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;
}

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)

std::string readString()
{
  int strLen = Read<int>();

  std::string retVal(strLen, '\0'); // no need to allocate extra space

  Read(&retVal[0], strLen);      // &retVal[0] gives access to the buffer

  return retVal;
}

I do believe that the last version is MUCH better. There is no longer any copying involved :)

你如我软肋 2024-10-10 02:09:11
 rawString[strLen] = '\0';

将 NUL 从您分配的空间末尾写掉。

如果strLen是10,那么你分配10个字符的空间,读取10个字符,并将这个NUL写入位置11。哎呀

 rawString[strLen] = '\0';

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文