代码:
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作为平台。
我无法弄清楚为什么在第二种情况下会出现运行时错误?
您的代码导致未定义的行为 。 未定义行为意味着任何事情都可能发生,行为不能被定义。 该程序运行纯粹的运气,其行为无法解释。
基本上,
如果您正在使用new
动态内存分配,您必须使用delete
来释放它。
如果你正在用new[]
分配动态内存,你必须使用delete[]
来释放它。
通过任何地址delete
未被new
返回的是未定义的行为。
这里是标准的引用。
按照C ++ 03标准§3.7.4.2-3:
如果释放函数通过抛出异常终止,则行为是未定义的。 提供给释放函数的第一个参数的值可能是一个空指针值; 如果是这样,并且如果释放函数是在标准库中提供的函数,则该调用不起作用。 否则,在标准库中提供给operator
delete(void*)
的值应该是之前调用operatornew(std::size_t)
或operator new(std::size_t, const std::nothrow_-t&)
,在标准库中提供给操作符delete[](void*)
的值应该是先前调用operator new[](std::size_t)
或operator new[](std::size_t, const std::nothrow_t&)
在标准库中。
在C ++中,最好使用智能指针而不是原始指针来使用RAII(SBRM) ,原始指针会自动处理内存释放。
这里有两个错误:
delete
未被new
返回的指针。 delete
由new[]
返回的指针 – 你需要使用delete[]
。 所以,第一个片段只能巧合使用,而且不会因为使用原始类型而出现错误。 如果是UDT,析构函数将不会运行。
此外,你应该使用容器和智能指针,而不是原始的new
和delete
。
因为你必须通过新的删除结果。 这就是事情的工作,即新/删除的API合同。
因为你改变了q
点的地址,然后试图删除它。
你只应该尝试delete
任何new
回报给你。 任何其他的是未定义的行为。