删除指针时避免程序崩溃

时间:2014-05-27 07:14:58

标签: c++

以下代码中的第二次删除会导致程序崩溃,因为它已被删除:

int* i = new int;
delete i;
delete i;

尝试使用异常捕获它也无济于事:

int* i = new int;
delete i;
try {
  delete i;
} catch(exception& e) { // program just crashes, doesn't go into this exception block
  cout << "delete failed" << endl;
}

如何执行安全删除(先检查指针指向的区域是否已被删除)?

或者如果不可能,如何吐出发生崩溃的行号(没有调试工具)?

5 个答案:

答案 0 :(得分:4)

delete不会尝试检测指针是否有效,它只是释放传递给它的指针。您可以在每次删除后将i设置为nullptr。并在再次删除之前检查if(i==nullptr)(尽管再次删除nullptr不会导致任何问题,因为删除nullptr no op ,它实际上什么都不做。“ / p>

如果你只是玩游戏,那么这种代码可能有助于更好地了解语言。但是在生产中你应该小心这些代码并消除它们。它也是一个很好的指示,您的代码可能有其他资源管理错误。

答案 1 :(得分:1)

现代C ++解决方案永远不会使用newdelete。只需让C ++自动处理所有内容。

unique_ptr<int> i = make_unique<int>();

shared_ptr<int> i = make_shared<int>();

无需删除它。如果您没有make_unique,可以write your own

答案 2 :(得分:0)

您可以在C ++ 11之前将您删除的指针设置为(0, NULL),或者在C ++ 11编译器之后设置为nullptr。然而,这仅仅解决了问题(见下面的例子):

void deletePointer(int *iptr) {
  delete iptr;
  iptr = nullptr;
}

没有便携式和标准测试来检查指针是否有效&#34;删除。如果您的编译器支持C ++ 11,那么您可以做的最好的事情就是使用智能指针。因此,您不必担心无效删除。

答案 3 :(得分:0)

{
  std::unique_ptr<int> i(new int);
}

答案 4 :(得分:0)

让我们首先说一个double delete is an undefined behaviour ......这意味着一个未定义的行为:)

请允许我提醒deleting a null pointer is a no-op。因此无需检查指针是否为空。

如果没有更多背景信息,答案是没有便携式解决方案

根据体系结构,操作系统,甚至是您使用的内存分配库,它将产生不同的效果,并为您提供不同的选项来检测它。

无法保证程序在第二次删除时会崩溃。它可能只会以一种只会在一段时间后崩溃的方式破坏内存分配器结构。

如果您的目标是检测到问题,那么最好的机会是设置程序以捕获崩溃信号(例如SIGABRT,SIGSEGV,SIGBUS ......)并在信号处理程序上打印堆栈跟踪,然后再允许程序执行终止/写入核心文件。正如我上面所说,这个可能可能不是内存损坏的地方......但它将是内存分配器/程序无法继续的地方更多。

这种侵入性较小。

使用带有调试选项的自定义内存分配器或内存分配器(例如Solaris中的libumem)可以帮助您更早或更准确地检测问题所在。问题在于通常会有更大或更小的性能损失。

如果您的目标是防止问题......那么您必须采用最佳做法......例如。

  1. 一般情况下使用RAII或智能指针,或者至少在整个程序中无法安全地建立内存所有权时使用它们。
  2. 至少,始终记得将已删除的指针设置为null。这并不保证任何东西,因为你总是可以进行并发删除...但它有助于减少可能发生崩溃的情况。