在C ++中正确使用delete vs delete []相对于char *

时间:2015-03-27 14:12:50

标签: c++ arrays string new-operator delete-operator

我有一段代码:

#include<iostream>

using namespace std;

int main()
{
    char * str = new char;

    cin >> str;
    cout << str;

    delete str;
}

VS

#include<iostream>

using namespace std;

int main()
{
    char * str = new char[30];  

    cin >> str;
    cout << str;

    delete []str;
}

当我使用STDIN向任一程序提供输入时,哪个程序确保没有内存泄漏?

这种怀疑产生了,因为我们的教授告诉我们,char *基本上只相当于一系列字符。因此,如果我像第一种情况那样分配堆内存并让str&#39; hold&#39;一个字符数组,如果我然后删除str,它是否完全删除了数组?我知道第二种情况是这样做的。

我已经完成了 - &gt;

delete vs delete[] operators in C++

delete vs delete[]

因此我知道delete []删除new []分配的内存,delete对new执行相同的操作。但是如果new本身分配连续的内存位置呢?

3 个答案:

答案 0 :(得分:2)

您的两个第一个代码示例都是错误的。

char * str = new char;  
cin >> str;

您只为单个字符分配了内存。如果您读取空字符串以外的任何内容,您将写入未分配的内存并且将具有未定义的行为。

  

如果我然后删除str,它是否完全删除了数组?

它只会删除您分配的一个字符。您在未分配的内存中写入的其余字符串不会受delete的直接影响。这不是内存泄漏,而是内存损坏。

VS

char * str = new char[];

这不是合法的c ++。必须指定数组大小。

编辑:修复后,只要您读取29个字符或更短的字符串,第二个代码就是正确的。如果你读了一个更长的字符串,你将再次得到未定义的行为。

  

但是如果new本身分配连续的内存位置怎么办?

没有。 new(与new[]相对)只分配和构造一个对象。而delete只会破坏和释放一个对象。

TLDR两个程序都没有内存泄漏,但第一个程序由于内存损坏而具有未定义的行为。

答案 1 :(得分:2)

我相信你误解了内存泄漏和缓冲区溢出之间的区别。

什么是缓冲区溢出?

当我们有一些存储器要存储一些数据时,会发生缓冲区溢出。当我们存储这些数据时,我们会在那里放置太多数据。例如:

int x[4];
x[0] = 7;
x[1] = 8;
x[2] = 9;
x[3] = 10;
x[4] = 11; // <-- Buffer Overflow!

您的代码显示潜在的缓冲区溢出,因为cin不知道您分配了多少内存。当使用char *参数时,没有真正的方法可以告诉它。因此,在您的第一个示例中,如果要写的任何字符串长于空字符串,则会导致缓冲区溢出。同样,如果要向第二个示例写入超过30个字符(包括空字符),则还会导致缓冲区溢出

什么是内存泄漏?

内存泄漏传统上以这种方式表示:

char *x = new char[30];
x[0] = 'a';
x[1] = '\0';
x = new char[10]; // <-- Memory Leak!

在代码中的这一点上,您无法在第一次分配时调用delete[]。您没有指向该指针的变量。这是内存泄漏

delete []做什么?

让我们考虑在某个地方有一些可以给我们大块记忆的桶。我们可以通过newnew[]从该存储桶中获取大块内存。当我们使用deletedelete[]时,我们会将这些内存块返回到存储桶中。

我们与newdelete达成的协议是,一旦我们在一块内存上调用delete,我们就不会继续使用它。我们不这样做,因为系统可能会重用那段内存,或者它可能已经删除了所有一起访问该指针的能力。

这怎么可能有效?

你有这段代码:

char *x = new char;
cin >> x;

我想告诉你它与这段代码基本相同:

char y;
cin >> &y;

在这两种情况下,您只为一个字符分配了空间。因此,当我们在delete上调用x时,我们只会删除一个字符。那里可能会破坏的代码部分是cin会认为有足够的内存分配给它将尝试写入该指针的任何字符串。

事实是,可能没有足够的空间。只有一个char的空间。甚至字符串"a"也会占用2个字符。

答案 2 :(得分:0)

你不能做这些事情。 char * ptr = new char; 表示您已分配sizeof(char)字节。 如果您将执行cin&gt;&gt; ptr,并传递超过1个字符,你将得到段错误,因为没有分配内存。

要分配一组字符,您需要以下一种方式进行: char * ptr = new char [size]; 它将分配size * sizeof(char)字节。 然后你可以使用cin&gt;&gt; ptr用数据填充它。