如果delete[] p 失败会发生什么?
假设我有一个指向动态分配的包含 10 个元素的数组的指针:
T* p = new T[10];
稍后,我想释放该数组:
delete[] p;
如果 T
析构函数之一抛出异常,会发生什么情况?其他元素仍然会被破坏吗?内存会被释放吗?异常会被传播,还是程序会被终止?
同样,当 std::vector
被销毁并且 T
析构函数之一抛出时会发生什么?
Suppose I have a pointer to a dynamically allocated array of 10 elements:
T* p = new T[10];
Later, I want to release that array:
delete[] p;
What happens if one of the T
destructors throws an exception? Do the other elements still get destructed? Will the memory be released? Will the exception be propagated, or will program execution be terminated?
Similarly, what happens when a std::vector<T>
is destroyed and one of the T
destructors throws?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我看不到它在标准中明确调用:
只是它们将以与创建相反的顺序调用
5.3.5 删除 [expr.delete]
即使抛出异常,内存释放也会完成:
我在G++中尝试了以下代码,它表明在异常之后不再调用析构函数:
执行:
这一切都导致了这个(非常旧的答案):
从析构函数中抛出异常
I can not see it explicitly called out in the standard:
Just that they will be called in reverse order of creation
5.3.5 Delete [expr.delete]
And that the memory deallocation will be done even if the exception is thrown:
I tried the following code in G++ and it shows that that no more destructors get called after the exception:
Execute:
Which all leads back to this (very old answer):
throwing exceptions out of a destructor
找不到有关析构函数的任何内容,除了
我猜想抛出后不会再调用析构函数,但我不确定。
Couldn't find anything about destructors except for
I guess that after throwing no more destructors are called, but I'm not sure.
永远不要那样做。如果已经存在活动异常,则将调用
std::terminate
:“砰,你死定了”。你的析构函数必须。不是。扔。抵抗。编辑:标准 (14882 2003) 的相关部分,15.2 构造函数和析构函数
[ except.dtor]
:用于玩耍的测试用例(在现实生活中,抛出从
std::exception
派生的东西,永远不要抛出 int 或其他东西!):Never do that. If there is already an active exception,
std::terminate
will be called: "Bang, you're dead". Your destructor must. Not. Throw. Resist.edit: Relevant section from the Standard (14882 2003), 15.2 Constructors and Destructors
[except.dtor]
:Testcase for playing around (in real life, throw something that is derived from
std::exception
, never throw int or something else!):要回答你的第二个问题,如果你使用 std::vector ,则不需要调用删除,你没有使用指针(我相信向量类是内部的,但这不取决于你来管理)。
To answer your second question, if you used std::vector instead, there wouldn't be any need for a call to delete, you're not using pointers (the vector class is internally I believe, but this is not up to you to manage).
好的,这是一些实验代码:
在 g++ 4.6.0 上运行代码给出了以下输出:
因此,一旦第一个析构函数抛出,
std::terminate
就会立即被调用。其他元素不会被破坏,并且内存也不会被释放。谁能证实这一点吗?Okay, here is some experimental code:
Running the code gave the following output on g++ 4.6.0:
So it would seem that
std::terminate
is called immediately as soon as the first destructor throws. The other elements are not destructed, and the memory is not released. Can anyone confirm this?如果抛出异常,则抛出异常。未能销毁的对象显然没有被正确销毁,数组中剩余的对象也没有被正确销毁。
如果您使用向量,问题是相同的,只是不在您的代码中。 :-)
所以,抛出析构函数只是一个坏主意(tm)。
就像@Martin 下面所示的那样,一旦我们进入析构函数,抛出的对象就正式不存在了。其他人或许也会恢复记忆。
然而,它显然包含一些复杂的东西,没有被冲洗者正确冲洗。如果该对象以及数组中跟随它的其他对象包含一些互斥锁、打开的文件、数据库缓存或共享指针,并且这些对象都没有运行它们的析构函数,那么我们可能会遇到大麻烦。
此时调用 std::terminate 来使程序摆脱困境,似乎是您所希望的!
If an exception is thrown, it is thrown. The object that failed to destruct is obviously not properly destroyed, and neither are the ones remaining in the array.
If you use a vector, the problem is the same, just not in your code. :-)
So, throwing destructors is just a Bad Idea(tm).
Like @Martin shows below, the object that did thrown is formally non-existent as soon as we enter the destructor. The others might have their memory reclaimed as well.
However, it obviously contained some complicated things that were not properly of flusher flushed. If that object, and the others following it in the array, contained some mutex locks, open files, database caches, or shared_ptrs, and none of those had their destructors run, we are likely in BIG trouble.
Having std::terminate called at that point, to put the program out of its misery, seems like something you would wish for!