【问题标题】:Try-Catch and Delete[] issueTry-Catch 和 Delete[] 问题
【发布时间】:2011-11-28 03:05:05
【问题描述】:

我在 try-catch 情况下遇到了一点问题,代码如下(非常简单):

struct Something
{
  int A, B, C;
  Something()
  {
    A = B = C = 0;
  }
  ~Something()
  {
    cout << "Destructor " << endl;
  }
};

int main()
{
  Something * s = new Something;

  //Something * s = new Something[5];

  try
  {
    delete[] s;
  }
  catch(exception& e)
  {
    delete s;
  }
  return 0;
}

我打算先尝试将指针作为数组删除,如果失败,进行简单的删除。

所以,当我第一次尝试使用“Something”数组时(如注释行中所示),它运行良好。但是当我现在尝试它时,我得到了一个可怕的错误。

有什么想法吗?

【问题讨论】:

  • 为什么要先将其作为数组删除?这可能会导致未定义的行为。
  • 换个顺序有用吗?
  • 不,它只会导致同样的问题。你试图做的是一个坏主意。

标签: c++ exception-handling try-catch delete-operator


【解决方案1】:

您尝试做的既不是合法的 C++,也没有任何意义。

new 的分配必须跟delete 的删除,delete[]new[] 的分配;这必须完全像那样发生,其他一切都是未定义的行为。

您不能“尝试看看您是否编写了正确的代码”。异常表示异常的运行时行为,但您的错误是静态的编译时错误,无法处理,但必须修复。 p>

但是,在您的代码中,您永远不应该不知道给定指针的含义!由于语言是静态类型的,原则上您应该始终了解所涉及的类型。如果你想传递对象(可能是多态的),那么任何需要动态分配的东西都应该包装在它自己的管理器类中(比如shared_ptrunique_ptr)。

【讨论】:

  • 这段代码实际上只是我从正在实现的 SmartPointer 类(带有模板)中提取的一小部分。所以想法是:我得到一个地址存储器(T *),当超出范围时,我将其删除。但是,我真的不知道该地址是用新的还是新的 [] 创建的,所以有“猜测”部分。 (并且*请*不要告诉使用 RAII)
  • @julio.alegria:看看unique_ptr 是如何实现的。关键是要有一个合适的删除器,你可以抽象它,并在实例化时确定。但无论你如何剥这只猫的皮,你都无法知道自己拥有什么样的指针。 C++ 中没有“随机指针”之类的东西,你必须猜测它的语义。
  • @julio.alegria:使用 RAII。抱歉,这是用 C++ 编写正确程序而不会造成痛苦的代码重复的唯一方法。您正在寻找哪些标准库中尚未提供的智能指针行为?
  • @julio.alegria,这就是引用计数器的用途。使用指向 int 的指针或指向包含 int 的另一个类的指针,并根据需要递增、递减。查看 Meyers 的《更有效的 C++》。
【解决方案2】:

将指针作为数组删除(反之亦然)是不正确且未定义的。它不会抛出异常。

您应该考虑RAII。例如,创建一个包含指针作为成员的类。构造函数分配内存,析构函数删除。

那么你有几个选择:

(1) 有两个构造函数,一个用于单个项目,一个用于数组。在类中放置一个布尔值,用于保存指针是指向一个项目还是一个数组,并在销毁时检查它并调用适当的删除函数。

(2) 使您的类成为接受布尔模板参数的模板类,并在编译时解决此选择。

【讨论】:

  • 必须有一个不使用库的解决方案。依赖库并不总是好事
  • @julio.alegria:“依赖库?”只要您感兴趣的平台支持并完成预期的工作,就没有理由避免使用库。最坏的情况是,如果你不能使用 C++ 标准库或 Boost,你可以自己写一个智能指针。
  • @julio.alegria:你不需要库来实现 RAII。
  • 我的意思是在使用它之前学习如何做某事(即使它很困难)会更好。否则我们为什么不学习使用 STL 而不是学习所有那些硬数据结构。我说的对吗?
【解决方案3】:

你完全误解了try/catch的语义。它们不捕捉错误,它们捕捉异常。如果您自己抛出异常或做一些保证会抛出异常的事情,您只能依赖创建的异常。在分配有new[] 的指针上调用delete 并不能保证会抛出异常,事实上,它不能保证执行任何特定操作。

【讨论】:

    【解决方案4】:

    所以我的 c++ 技能已经生疏了,但是在你调用 new[] 的地方调用了 delete[]。在您的示例中,您没有调用 new[]。

    【讨论】:

    • 这就是我使用 try-catch 的原因
    • 我明白你在做什么,但规则是你释放你 malloc 的东西,删除你的新东西,然后删除 [] 你新的东西 []。我认为这将取决于您偏离规则时的结果。
    猜你喜欢
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    • 2011-01-24
    • 2011-09-10
    • 2011-07-04
    • 1970-01-01
    相关资源
    最近更新 更多