为什么我们不能删除初始化的指针?

时间:2013-07-29 12:19:04

标签: c++ pointers memory-management

我正在使用一些随机值初始化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;
}

5 个答案:

答案 0 :(得分:16)

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

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

答案 1 :(得分:10)

问题在于此作业后:

s = "Harry";

然后您的s不再指向您已分配的内存。它指向不同的数组,或者const char[6]来确切。另一个数组未动态分配,并且不在堆上。你不能delete不在堆上的变量。

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

要修复代码,请使用"Harry"s复制到strcpy数组中,或使用std::string代替。

答案 2 :(得分:4)

你应该永远不会用这种方式用字符串常量初始化指针。它会造成内存泄漏,这可能非常危险。 当您使用new分配内存时,在堆中分配了50个char内存,并在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");

答案 3 :(得分:3)

char *实际上不是字符串。它是一个指向某个字符的指针,其中包含更多字符并以'\ 0'结尾。

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

另一方面,

std :: strcpy将字符串中的字符串从一个数组复制到另一个数组。不会更改任何指针,只会复制内存块。指向目标数组的指针后来仍指向目标数组,只有该数组中的数据发生了变化。

答案 4 :(得分:-1)

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

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