代码:
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作为平台。
我无法弄清楚为什么第二种情况会出现运行时错误?
答案 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)
这里有两个错误:
delete
new
未返回的指针。delete
new[]
返回的指针 - 您需要使用delete[]
。因此,第一个片段只能巧合,并且只有因为您使用的是原始类型才会出错。如果是UDT,则析构函数不会运行。
此外,您应该使用容器和智能指针,而不是原始new
和delete
。
答案 2 :(得分:1)
因为您必须将未经更改的结果传递给要删除。这就是事情的运作方式,即新/删除的API合约。
答案 3 :(得分:0)
因为您更改了q
指向的地址,然后尝试将其删除。
你应该永远尝试delete
无论new
返回给你。其他任何事都是未定义的行为。