2011-08-03 78 views
7

我遇到了一些我继承的代码的情况......老实说,我相信代码是正确编写的,但是这个错误似乎仍然表现出来。试着抓住不按预期工作

我会很快注意到,代码是从Linux交叉编译到LynxOS,我不确定这是否与错误有关。

基本上,在一个特定的情况下:

try { 
    std::vector<ClassA> x = SomeGeneratingFunction(); 

    //We get to here fine. X may be empty/unpopulated though. 
    if (x.size() < 1) 
    { 
     throw(MyException("It crashed.")); 
    } 
} 
catch (MyException e) 
{ 
    //Handle it. 
} 
catch (...) 
{ 
    //Handle it. 
} 

我们抛出给出的载体是无人居住的,但由于某些原因,罚球绕过catch子句 - 他们两个。它似乎只发生在这里 - 虽然我们通常不会形成一个if语句范围,但是它应该完全不相关,因为它仍然处于尝试范围之内。

PS:下面的代码实际上是一个函数的内容,即使它们应该全部由catch块处理,异常也会在函数调用时出来。

任何想法这可能吗?是的,这不是真正的代码/异常类,但异常类是你重载std :: exception的简单例子,SomeGeneratingFunction()确实返回一个好的向量,即使它是空的。我无法提供真实的代码,但是这是非常接近的,除非我可能把我写下来的任何小拼写错误写出来。

感谢您提前提出任何想法!

-w00te

+0

如果添加调试语句(在条件之前,抛出之前和之后)它会改变行为吗?如果你从图片中取出矢量怎么办? GDB在用“catch throw”运行时会做什么?你如何编译?尝试使用优化标志 – nhed

+0

按预期方式打印调试语句,但不会改变行为。这是一个庞大的系统,它具有复杂的分层结构,并且在不同的部分使用了大量的标志 - 但更重要的是,我们在任何你应该(或尝试)的地方使用尝试捕获,并且之前没有看到过这种情况。我想也许交叉编译器可能会对范围或类似的东西造成混乱,但我对编译器知之甚少。我有几个人看过去 - 我们可以通过做,而不是如果/抛出来解决它,但它是令人担忧的是解决一些事情,不应该发生 –

+2

我不知道,但可以考虑写渔线作为这* catch(const MyException&e)*可以避免为MyException拷贝构造函数付费,因为你会得到一个* throw *抛出的拷贝。 –

回答

0

我会重写它,而不使用try/catch。无论如何,在这里使用try/catch似乎不太合适。就你所知,异常可能无法在你的目标平台上运行。

+0

这就是我所做的,但我想了解它们有什么问题,因为它们在很多其他地方使用,而且看起来工作正常 - 其他代码可能需要调整。 –

+0

这不是我的问题的解决方案,但它最终必须做的事情,所以我会标记它,哈哈。用信息标记其他答案我也发现有帮助。 –

0
catch (MyException e) 

应改为:

catch (const MyException &e) 

我不知道为什么你的罚球看起来像一个函数或者,那种怪异。

编辑:

我已经与基于类似的渔获物的问题,虽然我同意,这不是在这种情况下,玩具足够。

编译看起来对我而言,是Try定义为有趣的东西?如果它是空的,可能是有意义的,如果你的编译器忽略catch语句而没有尝试。

+8

这可能是个好建议,但这不是问题。 –

+0

这样做不仅仅是通过停止形成副本来提高效率吗?还是说,如果没有它,实际上是否会将原始异常传播出去? –

+2

如果'MyException'不可复制(尽管编译器可能需要为此发布诊断),这个_could_会成为问题,但我认为这是不太可能的。 (哦,用'const'引用捕获更好。) – sbi

1

由于throw语句中的异常对象周围有一组备用括号,因此它看起来像一个函数调用。是否有可能定义了一个名为throw的函数?异常构造函数的参数使它不会成为Most Vexing Parse的受害者,但如果实际代码与示例不同,那么这是可能的。

+0

'throw'是一个关键字,你不能用这个名字来定义一个函数。 – interjay

+0

'throw MyException()'或'throw(MyException())'不可能是令人烦恼的解析,因为throw是关键字,而不是类型名称。我不知道任何C++编译器,如果您尝试使用'throw'作为函数的名称,则不会投诉。 –

+0

@interjay我想过,但也许有一些不正常的情况,'throw'是由宏重新定义的?我同意这种说法,但绝望的问题需要绝望的解决方案。 –

-2

让我们来解决这个问题......除非你想让程序崩溃,否则不要在C++中使用异常。我知道异常可能相当有用,但它们的性能很差,因为它引发了操作系统内核捕获的硬件异常。使用返回值和错误代码可能比抛出异常和捕获异常快500倍。

+9

-1。完全废话。 –

+0

为什么?这是一个设计建议。我做了基准测试以验证我的团队的另一位程序员确实查看了生成的程序集以了解异常机制。我们发现的结果可能令人惊讶,但问题严重。 – neodelphi

+0

http://stackoverflow.com/questions/307610/how-do-exceptions-work-behind-the-scenes-in-c –

9

由于catch (...)子句没有发现异常,我的回答并没有解决OP的问题。但对于那些在SO上发现这个问题的人,也许我的回答很有用,因为这解释了为什么第一次捕获失败。

我有一个类似的问题,我的catch(const std::exception& ex)只是不工作。事实证明,这是一个愚蠢的问题,因为我在C#和C++异常之间切换,在C#中,当抛出异常时需要指定new,而在C++中通常不需要(但是可以,但在这种情况下你扔一个指针而不是一个参考)。我不小心做

throw new std::runtime_error("foo"); 

所以

catch(std::exception* ex) 

会抓住它,但

catch(std::exception& ex) 

没有。当然,解决方案只是删除新的语句,因为这不是C++中的传统设计模式。

+0

在我的代码中出现了完全相同的问题!一直在搜寻很多时间的可能原因,最终结果是你提到的同样愚蠢的错误。 –

0

如果你有功能在一个较小的范围内MyException(甚至可能是偶然,最令人头痛的解析),那么throw MyException("It crashed")会调用该函数并引发返回值。