【问题标题】:Why can't we delete an initialized pointer?为什么我们不能删除一个已初始化的指针?
【发布时间】:2013-07-29 05:33:12
【问题描述】:

我正在用一些随机值初始化一个char 指针,当我试图删除它时,我无法删除它。这是为什么呢?

这是我正在做的事情:

int main()
{
    char *s = new char[50];    /* 
                                * I know there is no reason for 
                                * using new if initializing, but 
                                * in order to use delete we need 
                                * to allocate using new.
                                */
    s = "Harry";
    delete s;
    return 0;
}

【问题讨论】:

  • 请注意,当您删除一个数组而不是单个对象时,您需要使用delete [] 而不仅仅是delete。不过,这不是您的代码的唯一问题。
  • 每个人都忘了提到的是,char* = "Harry"; 首先不是一个有效的表达式,符合当前标准 (C++11) 的编译器应该拒绝它。

标签: c++ pointers memory-management


【解决方案1】:

您应该永远不要以这种方式使用字符串常量初始化指针。它会造成非常危险的内存泄漏。 当您使用 new 分配内存时,在堆中分配了 50 个字符的内存,其指针在 s 中返回。当您尝试使用 s="Harry" 初始化此值(错误方式)时,会在堆栈中分配一个新空间,使用此值初始化并在 s 中返回。

在堆栈中分配的内存不能使用delete 调用删除,因为它只在堆上工作。 此外,最初使用 new 分配的内存不能再使用 s 访问。因此,这里有内存泄漏。

在错误的初始化之后,您可以通过对程序进行一些小的更改来注意到指针 s 中的不同地址:

#include <stdio.h>

int main()
{
        char *s = new char[50];    
        printf("\n %u",s);  // print address before init
        s = "Harry";
        printf("\n %u",s);  // print address after init
//      delete s;           // cannot delete from stack
        return 0;
}

就像其他人已经建议的那样,应该使用

初始化一个字符数组
strcpy(s, "Harry");

【讨论】:

    【解决方案2】:

    如果你真的想练习指针,你需要修复你的代码。主要问题是您试图将字符串文字(此处为 const char[6])分配给指针 s 然后尝试通过调用调用未定义行为的 delete 来修改它(UB )。

    char *s = new char[50];    
    strcpy(s, "Harry");     // don't assign string literal to it
                            // re-assign pointer to string literal,
                            // lost pre-allocated memory position and caused delete to fail 
                            // it's UB to modify string literal
    delete []s;             // new[]/delete[], new/delete need to be called in pair. 
    

    只需改用std::string

    #include <string>
    std::string s("Harry"); // no worries
    

    【讨论】:

      【解决方案3】:

      问题是在这个赋值之后:

      s = "Harry";
      

      那么您的s 不再指向您分配的内存。它指向一个不同的 数组,或者准确地说是一个const char[6]。另一个数组不是动态分配的,也不在堆上。你不能delete不在堆上的变量。

      此外,通过在动态分配的内存被释放之前将s 指针更改为指向其他位置,会导致内存泄漏。

      要修复您的代码,请使用strcpy"Harry" 复制到s 数组中,或者改用std::string

      【讨论】:

        【解决方案4】:

        char* 实际上不是字符串。它是指向某个字符的指针,该字符后面有更多字符,并以 '\0' 结尾。

        像“abc”这样的 C(以及 C++)中的字符文字只是一个字符数组,编译器会默默地添加一个 '\0'。当您将数组分配给指针时,数组会静默地将指针转换为第一个元素。 s = "Harry" 的意思是,指针 s 被分配了字符串文字 "Harry" 中第一个字符的地址。所以旧值丢失了,因为这是动态分配的字符数组的地址,所以应该会发生泄漏。

        另一方面,

        std::strcpy 将字符串从一个数组逐个字符复制到另一个数组。不会更改指针,只会复制内存片段。之后指向目标数组的指针仍然指向目标数组,只是该数组中的数据发生了变化。

        【讨论】:

          【解决方案5】:

          我认为初始化指针不会发生这种情况。

          当使用指针时,你只能删除(释放)它指向的内存,而不是指针本身,因为它是一个自动对象,会在块的末尾被删除。

          【讨论】:

            猜你喜欢
            • 2022-10-15
            • 1970-01-01
            • 2012-08-23
            • 2017-06-22
            • 1970-01-01
            • 1970-01-01
            • 2011-07-21
            • 2017-01-05
            • 1970-01-01
            相关资源
            最近更新 更多