I was under the impression that using setjmp() and longjmp() in C++ was almost guaranteed to mess up the stack, since these functions don't perform unwinding like, say, exceptions do. This MSDN page, however, indicates that the Microsoft implementation can be told to invoke the destructors of local objects, which implies that careful use of these functions could be safe.
Is there a portable means of ensuring program correctness when using setjmp() and longjmp() in C++? Best practices in C++ indicate that exceptions are best not used for flow control, but in a situation that requires highly unusual flow (e.g., coroutines and closures), is it always preferable to use exceptions in lieu of these functions?
If you have some really weird requirement that doesn't allow you to control the flow of the program normally, with conditionals/loops/breaks, I would prefer to use an exception over jmp.
There are scenarios where using an exception to control flow is acceptable. I think one of Boost.Graph's search functions throws an exception to quickly return to the caller from deep recursion.
I've used them before, but only under one circumstance: I was creating an OS kernel in C for an OS class; they were used for exception handling.
My understanding is that they're used for exception handling when dealing with low-level code, like an operating system. For general C++ software, I'd just use try catch.
Related
Qt is not currently exception safe nor, it seems, is it ever likely to be. What restrictions does this place on C++ code which interacts with Qt?
Do I need to avoid all C++ exceptions in my code if I want to use Qt?
You can do the same two things you do with any other non-exception-safe library that you want to use in an application: Isolate it in exception-safe wrappers, or give up exceptions and adapt to its style. What you're really asking is whether the first is feasible.
For your literal question, you definitely don't need to avoid all exceptions. All of the Qt functions that return error codes, classes that don't clean themselves up properly, etc. can be wrapped up pretty easily. And you have no good reason to throw exceptions at Qt, so it doesn't matter that you can't. And you don't often pass Qt objects to non-Qt libraries that depend on exceptions. And so on. The trickiest it gets it thinking about how to write, e.g., a QImage wrapper that will destroy and throw if the real constructor succeeds with an invalid value, and that's not very hard.
But the big issue is that you can't throw exceptions through signal-slot connections. If you wanted to organize your code in the typical way, where low-level functions throw most of the exceptions and top-level functions do most of the exception handling, but you want to use Qt as most of your middle layer, that's probably not going to be pleasant.* For, say, a traditional heavy-controller MVC design, where most of the controller is built on Qt, your use of exceptions is going to end up being very local and not be all that helpful. On the other hand, with a MVA design or a smart-model design, most of your logic may not be dealing with Qt directly at all, so you can still go wild with exceptions within pretty large boundaries. (Of course that assumes you don't use Qt where you don't have to.)
* Even here, it's possible to wrap things up. For example, you can't throw across a thread join, condition wait, etc., but you can build futures and executors that pass exceptions between threads in a clean way. With the same kind of scaffolding, you could pass exceptions through slots. But that's reasonably heavy scaffolding, and you'll end up with a pretty different API than a typical Qt program, so it doesn't seem worth it.
Google C++ coding style recommends against C++ exceptions, and we don't use them too. For most of the STL library containers one can just ignore the exceptions, because normally they indicate critical errors and are difficult to handle anyway, so crashing is acceptable.
However there is a problem with multi-threading (std::thread), for example entering a non-recursive mutex twice throws an exception. This situation is not critical and could be handled by waiting.
My question is: anyone knows what is Google using as a threading library? Is there any C++ cross-platform threading library that doesn't use exceptions?
Thank you
It should be noted that Google's style guide does not not preclude the handing of exceptions rather the throwing of exceptions. I.e. deal with the problem, but don't make it any worse by throwing more exceptions.
In the case of re-entering a non-recursive mutex: that is clearly a programmer error rather than some unexpected bolt from the blue. The exception should be allowed to propagate up to the calling code so that it can be seen and dealt with as a bug. It should be noted that the Google Test framework does not rely on exceptions, but it can certainly catch and report them.
While Google's style guide takes an extreme position, there is no doubt that exceptions can highly problematic when writing reusable libraries. For example, we found developing with WinCE 6.0 that exceptions got sliced on re-throwing and on ARM platforms couldn't be reliably thrown across DLL boundaries. In addition, catching an exception could take several milliseconds, so they definitely shouldn't be used for non-exceptional circumstances (i.e. 'expected' errors) where real-time performance is required. The clue's in the name really.
The practices in Google's style guide dates back to the early nineties of the previous century, when threads were rather exotic beasts. As such, it doesn't make sense to wonder how that style and threads would mix. If you use "modern" (21st century) techniques like threads, you don't use Google's style guide and vice versa.
IIRC the reason that Google does not use exceptions is that much of their codebase is not exception safe, and they cannot afford to rewrite it.
From their site:
On their face, the benefits of using exceptions outweigh the costs, especially in new projects. However, for existing code, the introduction of exceptions has implications on all dependent code. If exceptions can be propagated beyond a new project, it also becomes problematic to integrate the new project into existing exception-free code. Because most existing C++ code at Google is not prepared to deal with exceptions, it is comparatively difficult to adopt new code that generates exceptions.
Given that Google's existing code is not exception-tolerant, the costs of using exceptions are somewhat greater than the costs in a new project. The conversion process would be slow and error-prone. We don't believe that the available alternatives to exceptions, such as error codes and assertions, introduce a significant burden.
Our advice against using exceptions is not predicated on philosophical or moral grounds, but practical ones. Because we'd like to use our open-source projects at Google and it's difficult to do so if those projects use exceptions, we need to advise against exceptions in Google open-source projects as well. Things would probably be different if we had to do it all over again from scratch.
Personally speaking I much prefer function return codes than exceptions. But regardless of one's own preferences or coding styles, the important thing is to catch problems where they occur, don't let them propagate, persist or cause mayhem.
What I do, especially during development, is on detecting any sort of error in any sort of thread I get the process to freeze itself. On Linux I raise the SIGSTOP signal. The benefit of that is that I can then attach with a debugger and see the whole process in all its broken glory.
The supposed ethos of C++ is "what you use, you pay for". However, this can be quite debilitating due to exceptions and their pervasive use in the STL.
Before anybody says "just turn exceptions on", life is not so generous with the programming environments we must live in. Mine is kernel programming where the execution environment does not provide enough C++ runtime to unwind the stack, etc.
STL containers will throw allocation failure exceptions when they cannot reallocate storage for their underlying backing stores. When exceptions are not enabled in the environment, the program will crash rather mysteriously: I have seen implementations straight-up abort or just assume that the allocation worked even if it did not.
Many C ADT libraries that I have come across deal with this problem upfront by returning an error code or having the error as an output parameter.
What is the "best" C++ way of dealing with this problem?
To clarify
I do not want to use the standard library, I cannot. I am not asking "how do I do that which cannot be done". I am asking: "given a clean slate, how should the container library be built."
That's easy: stop believing you should use the standard library for everything.
The standard library is intended to be the default place you go for functionality. However, that doesn't mean it is appropriate in every situation. Such as kernel programming, for example. This is a fairly niche environment, where you need direct and explicit control over things that the majority of C++ programmers don't care about.
The C++ standard mechanism for signaling failure, particularly of something like internal memory allocation from a container, is to throw an exception. The vast majority of applications will not bother to catch that exception; in the unlikely event that they are out of memory, they just die. Which is fine for them. Returning an error code in these cases is, at best difficult (consider reallocation of a std::vector<std::string>. What happens if one of the inner std::strings is what gets OOM? Who gets the error code? How would you even signal the failure of a constructor, since the exception is thrown by std::strings copy constructor?). And only people who really need to care will care enough to catch it.
You're working in a restricted environment, an environment that the standard library is not designed to handle. So... don't use it in that environment.
My suggesting is to track down a copy of EASTL. It's really designed for this sort of thing. The Github repo I linked you to has some bug fixes and so forth, but it's still mostly the same. It's not a bad bit of code. Their STL-like containers provide most of the interface, so they can be mostly drop-in replacements. But they provide special functionality to specifically control memory allocations. And they don't throw (or at least, you can turn off throwing).
It seems the problem is really your environment. Stack unwinding is not terribly complicated. I can see why you'd want to put some restrictions on it - throwing a 10 MB object is legal C++ - but even in kernel mode you should be able to support throwing std::bad_alloc through non-virtual calls.
With that in mind, the STL design is perfectly sane. The interface requires only minimal exception support, and the implementation can be tailored to the environment.
I have been programming in C++ on and off for about 5 years, why have I never seen exceptions used other than examples for examples sake?
Observation bias at work here.
A significant fraction of C++ code is for systems programming and embedded systems. (After all, C++ is just one of many options for applications programming, and many of the alternatives have fancier RAD environments, but in systems work, it's often the highest level language for which a compiler is available, by a wide margin). And most embedded systems as well as a significant chunk of systems development work have constraints that rule out exceptions.
If because of your focus, you tend to search out this sort of code, it's entirely possible that the C++ code you've seen doesn't use exceptions.
That doesn't mean that there isn't C++ code using exceptions -- there is, and a lot of it. It may just not appear in code designed to solve problems that are interesting to you.
Exceptions are a fairly late addition to the language, so I believe many C++ developers have never learnt to use them properly, and may feel more at ease using traditional (C style) error handling techniques.
I personally think they are indispensable in handling constructor failures (that is the foremost reason they were added to C++ after all), but they also require the correct use of other advanced (YMMV) techniques like RAII or smart pointers to avoid resource leaks.
I have been programming in C++ on and off for about 5 years,
why have I never seen exceptions used other than examples for examples sake?
I'm very curious about this.
I'm very curious about this since in 1996.
Sometime I think in 1996 C++ Exception Handling revolutionized the way I'm writing software.
I remember that I was reading about C++ Exception handling and I immediately understood the implications. Within minutes I was testing what happens, if an exception is thrown from a constructor.
Compilers for UNIX were not ready for C++ Exception Handling until G++ 3.0 I think (whe was this?).
Destructors were called for not constructed memory locations (on the stack) (in case of some exception was thrown).
Destructors were not called for successful constructed objects (on the stack) (in case of some exception was thrown).
delete was not called in case of an object created with new threw an exception from the constructor.
Compilers for Windows and OS/2 were ready in 1996/1997. They worked.
I remember Borland C++ for OS/2 and IBM CSet2 and Windows Visual C++.
Finally there was a method to abort construction of an object.
Finally one could allocate an object inside a constructor AND rely on the successful construction of this object in some other constructor.
Somehow I found out about all the rules. Not from books!
Years later books came out, claiming that C++ Exception Handling is a good way to catch array-out-of-bounds error or other problems for which I never stopped using assert.
Finally there was an easy method to provide the caller with complex information about some error without relying on stderr. Finally one did not need to debug some complex piece of software to find out, what was failing.
I cannot take people seriously, which are not using C++ Exception Handling.
It is impossible to check every fallible call.
It is impossible to reach the same level of quality of software without using C++ Exception Handling.
Why are such people still hired?
Why are there still platforms, which do not provide C++ Exception Handling.
I would never consider writing software for such a platform,
in the same way I would refuse writing a complex application in assembly code.
Curious. I work in C++ regularly, and it's been at least ten
years since I've seen any C++ code which doesn't use exceptions.
Anytime you have to propagate an error up a significant number
of stack frames, you use an exception.
Several reasons come to mind:
Exceptions shouldn't be very visible, since they are designed to be thrown deep in the bowels of a library and caught somewhere high up in the call stack (even as high as main()).
They are intended to signal exceptional (i.e., rare and unexpected) faults. For example, failure to open a file isn't particularly exceptional. So, by default, the iostream library doesn't throw an exception when it fails to open a file.
Exceptions are very expensive to throw, which encourages adherence to the design intent.
C++ libraries that throw exceptions don't interface easily with C programs.
I could say the same thing and it would not be biased a lot, if i define that this is true for a Microsoft world and RAD.
I think it is because today you don't use C++ programs per se but rather a mixture of high level language using C++ libraries. And often you have a managed-unmanaged boundary.
Throwing and catching exception through this boundary is like lighting a firecracker in you ass :) - [read mem leak or worse]
Moreover if you use COM objects you have to use COM exceptions, so the usage of standard C++ exception must reside internally in a often small library. In small libraries you dont have a need to use exceptions.
Because there is a huge discrepancy between "real-world" code and "text-book" code.
I work in a "large" software company and can honestly tell you that the stuff you see in production follows nearly 0% of the good practices you read about in good books.
Take Scott Meyers' Effective C++ book as an example. Should be a copy on every software engineer's desk, from east coast, to west.
Exceptions are too advance for beginners so these are not always shown in the examples, especially on books.
I'm speaking of desktop applications for Windows. In my observation (YMMV too), earlier phase of the development probably until initial releases. Many developers doesn't think of exceptions early on. That is why there are few codes with exception handling but if you had like 2 or 3 releases already or if your on maintenance phase, exceptions are being considered due to various deployment environments through error reports from customers.
Several reasons come to mind:
Exceptions shouldn't be very visible, since they are designed to be
thrown deep in the bowels of a library and caught somewhere high up
in the call stack (even as high as main()).
I don't know what you mean with "Exceptions shouldn't be very visible".
But I agree that catch-blocks should be rare -- and they are usually in main.
They are intended to signal exceptional (i.e., rare and unexpected)
faults. For example, failure to open a file isn't particularly
exceptional. So, by default, the iostream library doesn't throw an
exception when it fails to open a file.
that the iostream library does not throw exceptions makes it kind of unuseable.
Hiding errors from the caller!
This is so C like.
Exceptions are very expensive to throw, which encourages adherence
to the design intent.
Usually Exceptions are for system calls failing.
Since writing to a file or opening a file is not really inexpensive,
one would not care about Exceptions being expensive.
Also having to check for success is more expensive than using C++ Exception Handling.
Usually one would not create a try-catch block inside a time critical part of code.
C++ libraries that throw exceptions don't interface easily with C
programs.
What is C? Ah yes -- I remember -- something I gave up around 1996. Remember Turbo Pascal?
Exemptions are not used in examples because it is rarely the focus of many of the questions or something you want to know in the first place.
What important points about Structured Exceptions should every C++ developer know?
They are the Win32 equivalent to Unix signals, and let you catch CPU exceptions such as access violation, illegal instruction, divide by zero.
With the right compiler options (/EHa for Visual C++), C++ exceptions use the same mechanism as stack unwinding works properly for both C++ (user) exceptions and SEH (OS) exceptions.
Unlike C++ exceptions, SEH are not typed but all share the same data structure which has an exception code (the cause) and additional information on what code faulted and what the CPU registers held at the time of the fault. See GetExceptionCode and GetExceptionInformation for more details on this.
Also, SEH has "first-chance" handling, which allows you to log or otherwise handle the exception before unwinding destroys all the local variables.
I recently had a problem which was caused indirectly by SEH, specifically because of one feature of SEH which I think every developer should be aware of:
When SEH is used destructors are not called, so if you have cleanup code in your destructor it will not be cleaned up.
Our problem was caused by a Critical Section that was wrapped by an object with Lock in the constructor and Unlock in the destructor.
We had a deadlock situation and couldn't figure out why, and after about a week of digging through the code and dumps and debugging we finally understood it was because there was an exception that was handled by COM and causing the Critical section to stay locked.
We changed a compilation flag in VS in the project properties which tell it to run destructors even for SEH and that solved the problem.
So even though you may not use SEH in your code, you may be using a library that does (like COM) and that can cause unexpected behavior.
They should know that they are not part of Standard C++ - they are Microsoft invention and can be used in languages other than C++.
A Crash Course on the Depths of Win32™ Structured Exception Handling
That article is the reference on getting up to speed with SEH. 13 years later, is still the best there is.
There is a dedicated topic on MSDN for SEH vs. C++ Exception Handling Differences.
Some things a C++ developer should know if SEH is being discussed:
Writing C/C++ SEH Exception Handlers:
__try
{
// guarded code
}
__except ( expression )
{
// exception handler code
}
This is not C++ exception handling, is the MS specific extensions for hooking straight inot SEH. It works very differently from your run-of-the-mill C++ exceptions. You need a good understanding of SEH to use these.
Writing C/C++ SEH Termination Handlers:
__try {
// guarded code
}
__finally {
// termination code
}
Same as with the SEH handler, do not confuse this with C++ exception semantics. You need a good understanding of SEH.
_set_se_translator: this is the function that translates SEH exceptions into C++ type exceptions when asynchronous exceptions are used /EHa.
And finally, a personal opinion: should a C++ developer know SEH? After your first rookie .ecxr you'll understand that when the push come to shove C++ exceptions are just an illusion provided for your convenience. The only thing going on is SEH.
An important point is knowing when to use SEH and when to use standard C++ exceptions. First, choose only one system – mixing systems tends to be problematic, requiring a deep understanding of both to implement well. Second, at a high level, SEH is not limited to C++, while standard C++ exceptions are not limited to Windows. If this does not dictate your decision, choose standard exceptions unless they are inadequate (see the other answers for more details about what SEH can do).
A quote from Microsoft's documentation (dated 08/13/2018) supports this conclusion.
Structured exception handling (SEH) is a Microsoft extension to C to handle certain exceptional code situations, such as hardware faults, gracefully. Although Windows and Microsoft C++ support SEH, we recommend that you use ISO-standard C++ exception handling because it makes your code more portable and flexible. Nevertheless, to maintain existing code or for particular kinds of programs, you still might have to use SEH.
Why would the author of an extension recommend it not be used in most cases? Presumably because the extension was written for C and the current context is C++. The languages are similar, so porting SEH to C++ as a side-benefit was probably easy enough, even though only "particular kinds of programs" would truly benefit. (Or possibly some other reason; maybe the porting was started before C++ was standardized. History gets convoluted.)