9

I've run into a situation with some code I inherited... honestly, I believe the code is written correctly, but this error still seems to manifest.

I'll quickly note that the code is cross-compiled from linux to LynxOS, I'm not sure if that can have anything to do with the error.

Basically, in one specific case:

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.
}

We throw given the vector is unpopulated, but for some reason the throw bypasses the catch clauses - both of them. It only seems to happen here - though we woudln't usually do it form an if statement scope, but that should be completely irrelevant since its still in the try scope.

PS: The code below is actually the contents of a function, and exceptions come out of the function when called even though they should all be handled by the catch blocks.

Any ideas how this is possible? And yes, this isn't the real code/exception classes, but the exception class is the simple example you'd google of overloading std::exception, and the SomeGeneratingFunction() does return a good vector, even if it is empty. I cannot provide the real code, but this is exceedingly close barring any little typos I may have made writitng it off the top of my head.

Qix - MONICA WAS MISTREATED
  • 14,451
  • 16
  • 82
  • 145
John Humphreys
  • 37,047
  • 37
  • 155
  • 255
  • if you add debugging statment (before the conditional, before and after the throw) does it change the behavior? what if you take the vector out of the picture? What does GDB do when you run with a 'catch throw' ? How do you compile? Try mucking with optimization flags – nhed Aug 03 '11 at 15:49
  • Debugging statements print as expected and don't change the behavior. It's a massive system with a complex make heirarchy and lots of flags used in the different portions - but more importantly, we use try catches everywhere you should (or attempt to) and haven't seen this situation before. I thought maybe the cross compiler could have messed something up with scoping or something like that, but I don't know enough about compilers. I've had a few people look it over - we can work around it by doing if else instead of if/throw, but it's worrying to work around something that shoudln't happen – John Humphreys Aug 03 '11 at 15:53
  • 2
    I have no idea but consider writing the catch line as this *catch (const MyException& e)* to avoid having to pay for MyException copy constructor because you'll get a copy of that *throw* threw. – Simon P. Aug 03 '11 at 15:48
  • What is `Try`, with a capital 'T'? Is that just a typo? – Fred Larson Aug 03 '11 at 16:02
  • 2
    Also, you might try `x.empty()` instead of `x.size() < 1`. – Fred Larson Aug 03 '11 at 16:03
  • @w00te: Are you sure that exception is actually thrown? Is it caught somewhere else? – sbi Aug 03 '11 at 16:04
  • Can you tell if the `MyException` object is being constructed? – Fred Larson Aug 03 '11 at 16:13
  • Would finally() catch it as a test case? – Michael Dorgan Aug 03 '11 at 16:30
  • @Michael: It might, if C++ had `finally`. – Fred Larson Aug 03 '11 at 17:07
  • *"...and exceptions come out of the function when called..."*: Are the escaping exceptions of type MyException? – dolphy Aug 03 '11 at 17:08
  • 3
    There is not enough information here to answer the question. I shoved the posted code into a `main` function, added some `#include` and some minimal definitions for `MyException`, `ClassA` and `SomeGeneratingFunction` and `catch` worked as expected for me. – CB Bailey Aug 03 '11 at 17:16

6 Answers6

10

Since the catch (...) clause didn't catch the exception, my answer does not solve the OP's problem. But for others that found this question on SO, maybe my answer is useful, because it explains why the first catch failed.

I had a similar issue where my catch(const std::exception& ex) was just not working. It turned out to be a dumb problem in that I was switching between C# and C++ exceptions, and in C# you need to specify new when you throw your exception, while in C++ you normally don't (but you can, but in this case you are throwing a pointer and not a reference). I was accidentally doing

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

so

catch(std::exception*  ex)

would have caught it but

catch(std::exception& ex)

doesn't. Of course, the solution is just remove the new statement, as that is not the traditional design pattern in C++.

Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
  • Exact same problem occurred in my code! Had been googling for the possible reasons for a lot of time and in the end turned out to be the same dumb mistake you mentioned. – Pratik Singhal Nov 20 '14 at 13:25
1

Since you have a spare set of parentheses around the exception object in the throw statement, it looks like a function call. Is there any possibility that you've defined a function called throw? The parameter to the exception constructor keeps this from being a victim of the Most Vexing Parse, but that's a possibility if your actual code differs from your example.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • `throw` is a keyword, you can't define a function with that name. – interjay Aug 03 '11 at 17:08
  • `throw MyException()` or `throw(MyException())` couldn't possible be a vexing parse because throw is a keyword, not type name. I don't know of any C++ compilers that don't complain if you try to use `throw` as the name of a function. – CB Bailey Aug 03 '11 at 17:09
  • @interjay I thought about that, but maybe there's some perverse situation where `throw` was redefined by a macro? I agree it's grabbing at straws, but desperate problems call for desperate solutions. – Mark Ransom Aug 03 '11 at 17:11
  • Well, I like the idea. I do think its some sort of compiler glitch with the cross-compilation by this point. I've had alot of very compotent people check it out to no avail. Anyway, I tried your suggestion and it didn't seem to change anything - but thank you, it was an interesting thought! :) I probably won't get a solution to this one, but I'll leave it up for a while longer anyway. – John Humphreys Aug 03 '11 at 17:23
0

If you have a function MyException in a smaller scope (possibly even by accident, Most Vexing Parse) then throw MyException("It crashed") will call that function and throw the return value.

MSalters
  • 173,980
  • 10
  • 155
  • 350
0
catch (MyException e)

should read:

catch (const MyException &e)

I'm not sure why your throw looks like a function either, kind of bizarre.

Edit:

I've had problems with catches based on something similar, though I agree that it isn't sufficient in this toy case.

The compiler seems off to me, is Try defined as something funny? If it were empty it could make sense if your compiler ignored catch statements with no try.

Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
Tom Kerr
  • 10,444
  • 2
  • 30
  • 46
  • Wouldn't that just make it more efficient by stopping the copy from forming, or would the original exception actually propogate out of the function without it? – John Humphreys Aug 03 '11 at 15:47
  • 2
    This _could_ be the problem if `MyException` isn't copyable (although compilers are probably required to issue a diagnostic for that), but I think this is _highly unlikely_. (Oh, and catching by `const` reference is even better.) – sbi Aug 03 '11 at 15:53
  • Catching by reference might be a better practice (and, as @sbi noted, in that case it should be `catch (const MyException &e)`), it isn't the original problem. – AnT stands with Russia Aug 03 '11 at 16:07
  • @w00te: If you don't catch by reference you are susceptible to the slicing problem. This is when a class derived from MyException is thrown and subsequently caught by value with MyException, the resulting copy construction will slice the derived part out of the object. – Martin York Aug 03 '11 at 16:17
  • @Martin: whether there is slicing or not (i.e. if what you catch is what was really thrown), the fact is that the exception would be caught in one of the handlers. – David Rodríguez - dribeas Aug 03 '11 at 16:27
  • 1
    @sbi, if `MyException` wasn't copyable you wouldn't be able to `throw` it. A `throw` always makes a copy. – Mark Ransom Aug 03 '11 at 16:45
  • @Mark: Yeah, there's that. I forgot. `` – sbi Aug 03 '11 at 16:52
  • @David Rodríguez: I was just trying to answer w00te question in the comment above. The use of reference in this context has no bearing on the original question. – Martin York Aug 03 '11 at 18:11
-3

Let me slash the problem... Don't use exceptions in C++ unless you want to crash definitely the program. I know exceptions may be quite useful, but they have very poor performances because it raises up an hardware exception which is caught by the operating system kernel. Using return values and error codes can be 500 times faster than throwing and catching exceptions.

neodelphi
  • 2,706
  • 1
  • 15
  • 22
  • Why ? This is a design recommendation. I did benchmarks to verify that and another programmer of my team did look at the generated assembly to understand exceptions mechanism. What we found may be surprising, but the problem is serious. – neodelphi Aug 03 '11 at 17:13
  • http://stackoverflow.com/questions/307610/how-do-exceptions-work-behind-the-scenes-in-c – Fred Larson Aug 03 '11 at 17:17
  • 1
    Faster is not synonymous with more stable. – dolphy Aug 03 '11 at 17:18
  • 1
    It is possible to create intelligent structures which will check that an error code has been read or not. Using that mechanism you have the same stability as with the exceptions. Plus, there may be hard to track bugs when an exception is thrown during another exception handling. Concerning performances, exceptions do not add any overhead if they are not thrown - however, using exception for example to check correctness of user input is a bad design. Exceptions must be only "exceptional" and avoided as much as possible. – neodelphi Aug 03 '11 at 17:27
-3

I would just rewrite it without using try/catch. Doesn't seem appropriate to use try/catch here anyway. For all you know, exceptions may not work on your target platform.

Jonathan Sternberg
  • 6,421
  • 7
  • 39
  • 58