【问题标题】:Programme crashes while deallocating a character array释放字符数组时程序崩溃
【发布时间】:2012-11-29 13:30:31
【问题描述】:

当我在调试模式下运行使用以下代码创建的 .exe 时,它​​显示一些断言失败并且程序崩溃但是当我运行从以下代码的发布模式创建的相同 exe 时,它​​工作正常。

请帮助确定为什么我在调试模式下出现断言失败,但在发布模式下却没有。

#include<iostream>
using namespace std;
#include<string.h>

void main()
{
    char *buf  = new char[5];   //pre-allocated buffer
    buf = "Hello";
    delete [] buf;
    getchar();
    //cout<<buf;
    //string *p = new (buf) string("hi");  //placement new
    //string *q = new string("hi");  //ordinary heap allocation
}

【问题讨论】:

  • 注意,在这种情况下,你可以说char buf[] = "Hello";,你会得到一个你甚至不必解除分配的副本。
  • 在 C++ 中你很少需要 C 字符串,你应该使用 &lt;string&gt; 代替。在您实际需要 C 标头的少数情况下,您应该改用 C++ 标头(例如:)。

标签: c++


【解决方案1】:
 char *buf  = new char[5];   //pre-allocated buffer

在这里您定义一个指针,并将其初始化为指向一个动态分配的缓冲区,其中有 5 个字符的空间。

buf = "Hello";

在这里你将指针初始化为指向字符串字面量的开头。

 delete [] buf;

在这里你删除[] buf 指针,但 buf 指针不再指向你 new[] 的任何东西,它指向字符串文字。您只能删除/删除 [] 指向您从 new/new[] 获得的内容的指针。所以你会得到未定义的行为,并且可能会崩溃

您可能打算将字符串的内容复制到您新建的缓冲区中。请记住考虑 nul 终止符:

int main()
{
    char *buf  = new char[6];   //pre-allocated buffer
    strcpy(buf, "Hello");
    delete [] buf;
    getchar();
    //cout<<buf;
    //string *p = new (buf) string("hi");  //placement new
    //string *q = new string("hi");  //ordinary heap allocation
}

不过,在 C++ 中,您宁愿使用来自 #include &lt;string&gt; 的 std::string;

std::string = "Hello";

【讨论】:

  • 感谢您的回复。我现在明白了。但是为什么程序在发布模式下运行不会崩溃。
  • @viku 很难说。当你的代码做了一些未定义的事情时,几乎任何事情都可能发生。它可能会崩溃,它可能会破坏你的记忆,它可能看起来可以工作等等。
【解决方案2】:
  1. void main 是错误的。 main 返回int。没有例外。
  2. 你正在做delete[] "Hello""Hello" 是字符串文字;你不能delete它。

【讨论】:

  • 感谢您的回复。我现在明白了。但是为什么程序在发布模式下运行不会崩溃
  • @viku 这是未定义的行为 - 任何事情都可能发生。
【解决方案3】:

当你这样做时:

buf = "Hello";

您基本上是在更改buf 指向只读内存区域的指针值(内存地址),因为"Hello" 是字符串文字,因此存储在只读内存中。

然后您尝试释放该内存,从而导致崩溃。

另外,"Hello" 的长度是 6 字节,而不是 5。

【讨论】:

    【解决方案4】:

    因为未定义的行为意味着任何事情都可能发生。问题是buf = "Hello" 将字符串文字的地址分配给buf,然后尝试删除该文字。在调试模式下编译时,检查代码看到地址不能被删除;在发布模式下,检查没有完成,删除只是踩在不重要的东西上。

    【讨论】:

      【解决方案5】:

      您正在尝试解除分配字符串文字"Hello"。这一行:

      buf = "Hello";
      

      重定向指针 buf 指向文字"Hello"。您可能打算这样做:

      char *buf = new char[6]; //need one extra space for terminating NUL character
      strcpy(buf, "Hello");
      

      【讨论】:

        【解决方案6】:
         char *buf  = new char[6];   //pre-allocated buffer
         strncpy(buf, "hello", 6);
         delete [] buf;
        

        buf = "你好";会改变 buf 的值,从一个指向 new char[6] 的指针到一个指向“hello”的指针,一个不在堆中的内存块。

        【讨论】:

        • 1.当它与字符串无关时,它伪装成一个字符串函数。 2. 它抽象了原本不应该抽象的行为。问题 1+2 导致人们不恰当地使用它(因为它没有适当的用途)。例如。在上面的代码中,buf[5] 最初是未初始化的。
        • @melpomene:我有点同意它不会做任何 memcpymemmove 加上 memset 无法完成的事情。 (最大的区别是,它将目的地零填充到您传入的大小;因此memset。)不过,在其辩护中,它的意思是(并且现在)只是strcpy 的更安全版本。我认为裸字符数组根本不应该被赋予字符串的特殊地位。一个字符串应该是一个char*一个长度,或者一个数组应该能够知道它的大小。
        • 这并不是strcpy 的更安全版本。它不是strcpy 的更安全版本。它根本不是一个字符串函数。
        • @melpomene:你过于戏剧化了。在某些特定情况下,C 字符串可以在 C++ 中使用。
        • “可以想象的”是什么意思?
        猜你喜欢
        • 1970-01-01
        • 2023-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多