在释放动态内存时,Visual Studio 中的堆损坏错误

Heap corruption error in Visual Studio while freeing dynamic memory

本文关键字:损坏 错误 Studio Visual 动态 释放 内存      更新时间:2023-10-16

我在使用将数字连接到字符数组末尾的函数时遇到问题。老实说,我看不到问题:

void x(int num, char* originalArray) {
    char* concat_str = new char[1];
    sprintf(concat_str, "%d", num);
    for (int i = 0; i < 1; i++)
        originalArray[i + 10] = concat_str[i];
    delete [] concat_str;
   }

错误消息是:

检测到堆损坏:在 0x01204CA0 处的正常块 (#147( 之后。CRT 检测到应用程序在堆缓冲区结束后写入内存。

有什么想法吗?我是一个初级程序员,但我做过很多次同样的事情,从来没有遇到过这个问题。谢谢。

concat_str需要足够大,以容纳num中的位数加上一个空终止符。 由于它的大小为一个,因此您只有足够的空间容纳空终止符。 尝试添加任何其他内容是未定义的行为,因为它访问您不拥有的内存并导致堆损坏。

你正在为concat_str分配一个字节,并冲刺需要更多空间的东西。

首先,请注意,您的API是一个C api。如果要在C++中使用动态数组,请使用 std::vector<char>

但是,假设您需要坚持使用 C API,则无法保证您的originalArray足够大以保存结果。此外,临时缓冲区是不必要的。

应按如下方式修改 API 和实现:

  1. 取目标的大小,以保证它不会写超过其末尾。

  2. 将字符串就地写入目标缓冲区。将其放入临时缓冲区,然后复制到目标位置是浪费时间。

  3. 使用snprintf,而不是sprintf。后者并不安全:您无法保证它不会写入缓冲区末尾。

  4. 您应该断言偏移量至少小于目标大小的前提条件。

    如果前提条件成立,则目标将始终正确零端接,尽管num的文本表示形式可能不适合它。

  5. 您可以返回适合值所需的目标长度。

因此:

size_t fun(int num, char * dest, size_t dest_size) {
  const size_t offset = 10;
  assert(dest_size > offset);
  return offset + snprintf(dest + offset, dest_size - offset, "%d", num);
}