运行时检测内存删除

时间:2011-07-31 16:56:23

标签: c++ windows pointers memory-corruption

代码:

int *ptr = new int[10];
int *q = ptr;
delete q;

运行正常,没有任何问题(没有运行时错误)。

但是,以下代码:

int *ptr = new int[10];
int *q = ptr;
q++;
delete q;

导致运行时错误。

我使用Microsoft Visual Studio-8和Win-7作为平台。

我无法弄清楚为什么第二种情况会出现运行时错误?

4 个答案:

答案 0 :(得分:9)

您的代码导致未定义的行为。未定义的行为意味着任何事情都可能发生,行为无法定义。该计划只是运气纯粹,其行为无法解释。

基本上,

如果您使用new分配动态内存,则必须使用delete取消分配。

如果您使用new[]分配动态内存,则必须使用delete[]取消分配。

将任何地址传递给delete并未由new返回,这是未定义的行为。
以下是标准的引用。

根据 C ++ 03标准§3.7.4.2-3:

  

如果通过抛出异常终止释放函数,则行为未定义。提供给解除分配函数的第一个参数的值可以是空指针值;如果是这样,并且如果解除分配功能是标准库中提供的功能,则该呼叫无效。否则,提供的值   标准库中的运算符delete(void*)应该是先前调用标准库中的运算符new(std::size_t)operator new(std::size_t, const std::nothrow_-t&)返回的值之一,并且值提供给运算符{{1标准库中的标签库应该是前一次调用delete[](void*)或者返回的值之一   标准库中的operator new[](std::size_t)

在C ++中,最好使用 RAII(SBRM) ,使用智能指针而不是原始指针,这会自动处理内存释放。

答案 1 :(得分:3)

这里有两个错误:

  1. 您不能delete new未返回的指针。
  2. 您不能delete new[]返回的指针 - 您需要使用delete[]
  3. 因此,第一个片段只能巧合,并且只有因为您使用的是原始类型才会出错。如果是UDT,则析构函数不会运行。

    此外,您应该使用容器和智能指针,而不是原始newdelete

答案 2 :(得分:1)

因为您必须将未经更改的结果传递给要删除。这就是事情的运作方式,即新/删除的API合约。

答案 3 :(得分:0)

因为您更改了q指向的地址,然后尝试将其删除。

你应该永远尝试delete无论new返回给你。其他任何事都是未定义的行为。