When we write a program in C, it is possible that we will call some libraries that were wrote in C++ but had a C interface. Then it may happen that when we call these libraries, a C++ exception will occur. So my question is how we can handle this situation. I am more interested in this problem from a C++ developer's perspective. Suppose I am developing a C++ library that will be invoked by a C program, should I stop using exception and instead return error codes? Another situation is that if I have already a fully developed C++ library that uses exception, how can I transfer this library in a quick way that will only use error returning method?
You have to catch all exceptions on the C++ side and convert them to appropriate error returns in C, which may include specific error codes where appropriate. This doesn't mean that you stop using exceptions — you can still use them in C++ — but you can't expose them to C, they become an implementation detail.
A typical wrapper can be structured as follows:
// thingy-wrapper.h, typically included from C code:
#ifdef __cplusplus
extern "C" {
#endif
// create a typedef visible to C that doesn't expose the layout of
// the implementation.
typedef void *thingy_t;
// wrapper for std::string Thingy::get_name()
char *thingy_get_name(thingy_t t);
#ifdef __cplusplus
}
#endif
// thingy-wrapper.cpp, implements the wrapper, compiled with C++:
#include <thingy-wrapper.h>
#include <thingy.hpp> // declares Thingy class
char *thingy_get_name(thingy_t t_)
{
try {
Thingy& t = *static_cast<Thingy*>(t_);
std::string name = t.get_name();
return strdup(name.c_str());
}
catch(...) {
return NULL;
}
}
In this simple example, the caller of thingy_get_name can detect that an error occurred, but cannot find out the details of the error. A more realistic example would catch specific exceptions, and set a last_error variable to an error code or message before returning NULL. ... would only be caught as a last resort, and would set last_error to a generic UNKNOWN_ERROR value. A separate API for querying the last error, such as thingy_last_error(), would be available for the more careful callers of thingy_get_name().
The separation between error and non-error results enables code that doesn't care about the cause of errors to simply check if it received NULL, while allowing more conscientious code to properly propagate or report the error. If your library is multi-threaded, make sure that last_error uses thread-local storage.
Then it may happen that when we call these libraries, a C++ exception will occur. So my question is how we can handle this situation.
The C code cannot handle this situation. C code cannot deal with C++ exceptions.
Suppose I am developing a C++ library that will be invoked by a C program, should I stop using exception and instead return error codes?
No. If you want the C++ library to be consumed by C++ code you should use native C++ error handling. Which means exceptions.
However, the interface that you expose to the C code must not throw exceptions. Typically this means writing an adaptor layer that catches exceptions raised by the C++ library, and converts them into error codes to be consumed by the C code.
Another situation is that if I have already a fully developed C++ library that uses exception, how can I transfer this library in a quick way that will only use error returning method?
There's really no shortcut here. You have to write the adaptor that converts C++ exceptions into C error codes. You'll be writing an adaptor anyway if you want the library to expose interfaces for both C and C++ consumers. So the aspect of error handling is just another thing to take care of with this adaptor.
Exception are not caught in C so if you want to catch them then in your C code or your C++ code you have to write the wrappers very carefully.
Also make sure that in your C++ functions you have your functions declared as:
extern "C"
You may also check How to mix C and C++
Related
I am developing C++ component dll that can be used by C or C++ applications.
The exposed dll functions are as follows
#include <tchar.h>
#ifdef IMPORT
#define DLL __declspec(dllimport)
#else
#define DLL __declspec(dllexport)
#endif
extern "C" {
DLL bool __cdecl Init();
DLL bool __cdecl Foo(const TCHAR*);
DLL bool __cdecl Release();
}
the internal implementation of these functions are C++ classes which are not exposed, I assume using this style the dll can be used either in C or C++ apps.
The problem is I do not handle any type of c++ exception (i.e. bad_alloc) and I left this stuff to the caller (the higher layer).
After much debate with my colleagues that I should catch all the exceptions and return error code or at least false because in case of C application it can not handle C++ exceptions? is that true? and what I should do in general? is there a rule of thumb for handling exeptions if you are developing component that will be used by other system.
C doesn't have exceptions, therefore in general you should catch all exception and return an error code and/or provide a function that returns the information about the last error.
If this is Windows using MSVC then yes you can catch exceptions in C but you can't catch them that well. C++ exceptions are fed through the OS ABI's Structured Exception Handling mechanism, and Microsoft have a __try, __except, __finally C extension to handle OS structured exceptions. Note that these include access violations, divide-by-zero, etc. that you'd normally want to terminate your program and log a bug report. You can identify C++ exceptions by code 0xE04D5343 (4D 53 43 = "MSC") and throw the rest on.
That all said, you probably don't want to be throwing exceptions across a DLL boundary, and certainly not if you're only exposing a C API.
As a general rule, you should never allow C++ exceptions to propagate beyond a module's boundary. This is because the C++ standard does not specify how exception propagation has to be implemented, and as such this is compiler (and compiler flags) and operating system dependent. You cannot guarantee that the code calling your module will be compiled with the same compiler with the same compiler flags as your module. In fact, as you're demonstrating with this question is that you cannot guarantee that code calling your module will be written in the same language.
For more details, please refer to Item 62 in C++ Coding Standards by Sutter and Alexandrescu.
Ok, since it was asked for:
C++ example code:
#include <typeinfo>
#include <exception>
extern "C" {
void sethandler(void (*func)(void)) { std::set_terminate(func); }
int throwingFunc(int arg) {
if (arg == 0)
throw std::bad_cast();
return (arg - 1);
}
}
C example code:
#include <stdio.h>
extern int throwingFunc(int arg);
extern void sethandler(void (*func)(void));
void myhandler(void)
{
printf("handler called - must've been some exception ?!\n");
}
int main(int argc, char **argv)
{
sethandler(myhandler);
printf("throwingFunc(1) == %d\n", throwingFunc(1));
printf("throwingFunc(-1) == %d\n", throwingFunc(-1));
printf("throwingFunc(0) == %d\n", throwingFunc(0));
return 0;
}
When I compile these two, link them together and run this (Ubuntu 10.04, gcc 4.4.5, x64), I get:
$ ./xx
throwingFunc(1) == 0
throwingFunc(-1) == -2
handler called - must've been some exception ?!
Aborted
So while you can catch exceptions from C, that's hardly sufficient - because C++ runtime behaviour after std::terminate() is undefined, and because the handler gets no status information whatsoever (to distiguish exception types and/or sources). The handler cannot clean up anything.
Btw, I've deliberately chosen std::bad_cast() as exception type in this example. This is because throwing that illustrates a difference in behaviour between std::set_unexpected() and std::set_terminate() - the unexpected handler will get called for all non std::bad_* exceptions, while in order to catch standard exceptions, a terminate handler is required ... see the dilemma ? The harness is too wide to be of practical use :(
Only propagate exceptions to the caller if the caller is designed to handle them. I guess in your case terminate() will be called immediately once any exception escapes C++ code because from the point of C++ runtime that exception has not been handled.
The same situation arises in COM servers design - the clients can be in whatever language/technology. The rul is that no exceptions should escape COM server methods - all exceptions must be caught and translated in HRESULT and (optionally) IErrorInfo. You should do similarly in your situations.
In case C code is sandwiched between two layers of C++ code propagating exceptions to C code is still a very bad idea.
I'm using an unmanaged DLL with a function that throws std::exception.
I'm using a .NET DLL wrapper so it can be distributed to use in .NET programs.
I would like to be able catch the message from the native exception but all I'm getting is System.Runtime.InteropServices.SEHException("External component has thrown an exception.")
Is there any way to propagate the exception details? Maybe I should export a custom exception from the native DLL? How would I do this?
Thanks
native DLL:
__declspec(dllexport) void __stdcall W32DLLFunc(int param) {
if (param < 0) {
throw new exception("Error: param must be > 0");
}
...
}
.net DLL:
[DllImport("nw32.dll", CharSet = CharSet::Auto)]
static void W32DLLFunc(int param);
vb.net program:
Try
W32DLLFunc(-1)
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Native C++ exceptions are native C++ exceptions. They don't work with things that aren't C++. They even don't work between different versions of C++.
Native C++ exceptions are not good for interoperability.
The standard mechanism for returning error information from DLLs is to return a value to indicate success or failure and to use SetLastError and GetLastError to communicate an error code if the function failed.
If you want a standard mechanism to return more information than an error code you need to look at COM, which has IErrorInfo.
But it would be simpler just to define some error codes.
If possible, I would alter the original DLL so that it doesn't leak exceptions at all. If this is impossible because existing C++ clients depends on the current design then I would add a parallel API: a new version of each exported function that calls the original, catches exceptions and returns error codes. This is all boilerplate that can be hidden in macros. If you can't touch the DLL I would add a native wrapper to translate the exceptions.
Update
As suggested by IInspectable, another option is to create a mixed-mode assembly.
Add a .Net class to your existing C++ library. This should provide a wrapper for each API function that calls the original API, catches any exception, copies the details into a .Net exception and throws the .Net exception.
By keeping all the native exception handling within the DLL this avoids the problems with C++ exceptions crossing DLL boundaries. The wrapped exceptions can be consumed in any .Net language without the need to create declarations for the exported functions. The only disadvantage is that you need an additional API for interoperability with other native code.
I have written a C++ File Library which have exception and error codes. Exceptions can be disabled when the program is running. In that case, the user have to check the error codes. Of course, when exception throwing is enabled, error code won't be returned because exception is thrown before the called function returns. Currently, exceptions still could be thrown when disabled (bug). I'll fix that soon. Someone comment to me that it is considered bad design to have both exception and error codes. I agree with him and I am about to remove the error codes and have library throw custom derived exceptions with more error information. But I hesitate. I like to have this hybrid approach for performance reasons. This is what I am thinking of doing: keeping exception throwing and error codes but exception throwing is disabled through macro at compile time instead of runtime.
If user define the following in a common config file
#define ELMAX_EXCEPTION 1
The follow code
int Write(std::wstring str) ELMAX_THROW_OR_NOT;
would expand to either of the 2.
// under C++11 compiler
int Write(std::wstring str) noexcept;
// under C++98 compiler
int Write(std::wstring str) throw();
If ELMAX_EXCEPTION is not defined or is zero, the macro would expand to nothing.
int Write(std::wstring) ;
The reason I want to do this, is for library user who wants the performance gain of not having the compiler generating the stack unwinding code (for exception) and compiler can better optimize such functions. My C++ file library is using C file API and the only thing which could throw exception is new keyword, which I intend to add nothrow. The UTF-8 code can also throw exceptions (need to be changed too)
char *parr = new (nothrow) char[num];
if(parr==NULL)
// handle it either through error code or throw exception (if enabled)
Please kindly advise if I should have a pure exception approach or a hybrid approach (as mentioned), for my library errors. Thank you.
It depends on what you want to do with the library. Obviously exceptions are better from a design point of view, but it's true that they're often disabled for some kinds of apps (such as immersive 3D games).
I'm using libjpeg right now to save JPEG images. If there is an error, libjpeg's default behavior is to call exit(), which I want to avoid since it's not a fatal error for my program. libjpeg allows you to use your own error manager, and mandates that if you use your own error_exit() function (which calls exit() by default) you must not return control to the caller. libjpeg suggests using setjmp.h to meet this requirement and not exit() the program.
However, I am writing a C++ program, and I have access to exceptions. This question's answer states it's safe (as in well-defined behavior) to throw an exception from the callback. But it doesn't mention dynamic libraries, and there's a general rule of thumb that you don't throw exceptions across dynamic library boundaries.
Here's an example:
#include <iostream>
#include <jpeglib.h>
#include <cstdio>
#include <stdexcept>
static void handleLibJpegFatalError(j_common_ptr cinfo)
{
(*cinfo->err->output_message)(cinfo);
throw std::runtime_error("error in libjpeg, check stderr");
}
int main()
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE* file = std::fopen("out.jpeg", "wb"); // assume this doesn't fail for this example
try
{
cinfo.err = jpeg_std_error(&jerr);
jerr.error_exit = handleLibJpegFatalError;
// let's say this triggers a fatal error in libjpeg and handleLibJpegFatalError() is called
// by libjpeg
jpeg_create_compress(&cinfo);
}
catch (...)
{
std::cerr << "Error saving the JPEG!\n";
}
jpeg_destroy_compress(&cinfo);
std::fclose(file);
}
What I would like to know is: can I throw an exception from this callback, and catch it back in my application, even if libjpeg is compiled as a dynamic library? libjpeg may be a static or dynamic library, and if it's a dynamic library it may possibly be built with a different compiler. However, the code that throws and catches the exception will certainly be in the same compilation unit. Is the above code safe?
FYI, I'm developing for OS X and Windows (and keeping the future of a Linux possibility in mind), so I'm more interested in if this is known to be well defined behavior in general, and not for a specific platform/compiler.
The other answer applies here. Nothing will get trashed when unwinding the stack. It doesn't even matter if the library uses some crazy calling convention internally, as long as it doesn't specifically mess with your C++ implementation's exception handling structures (which it wont as a C program). No C++ implementation that I know of finds the catch block by popping off stack frames (that would make optimization a nightmare), they all maintain internal structures for exception handling. As long as a call lower down in the call chain doesn't mess with those structures, stack unwinding will work perfectly fine for all of your personal code. Now, in general, it's quite possible that this would leave a library with a messed up internal state as you never return execution to the library for cleanup, but in the case of your error callback, libjpeg expects for control flow to not return and has presumably already cleaned up after itself.
In this case, I would go for it. In general, I would only throw fatal exceptions from a C callback.
Hope that helped.
It's not safe. Depending on how the relevant non-C++ library code was compiled, the necessary unwind tables may not exist. This is just a practical reason why it might fail; the conceptual reason is that it's simply undefined behavior.
You should follow the documentation and use setjmp/longjmp to get just outside the call to libjpeg code, then throw an exception immediately in the if (setjmp(...)) { ... } body if you want to use exceptions.
As discussed in other answers, it ought to be safe as long as you are in control of all the modules and they will be built by the same toolchain (inc. statically linking).
But I want to add a caveat here that some toolchains require this support to be turned on, since libjpeg's functions are marked extern "C". By default, Visual Studio assumes that such functions will not propagate exceptions.
If you don't turn this on, expect much pain. I spent hours on a testcase almost identical to yours before I realised this. 😃
I am writing a custom C++ exception class (so I can pass exceptions occuring in C++ to another language via a C API).
My initial plan of attack was to proceed as follows:
//C++
myClass
{
public:
myClass();
~myClass();
void foo() // throws myException
int foo(const int i, const bool b) // throws myException
} * myClassPtr;
// C API
#ifdef __cplusplus
extern "C" {
#endif
myClassPtr MyClass_New();
void MyClass_Destroy(myClassPtr p);
void MyClass_Foo(myClassPtr p);
int MyClass_FooBar(myClassPtr p, int i, bool b);
#ifdef __cplusplus
};
#endif
I need a way to be able to pass exceptions thrown in the C++ code to the C side. The information I want to pass to the C side is the following:
(a). What
(b). Where
(c). Simple Stack Trace (just the sequence of error messages in order they occured, no debugging info etc)
I want to modify my C API, so that the API functions take a pointer to a struct ExceptionInfo, which will contain any exception info (if an exception occured) before consuming the results of the invocation.
So an C++ method exposed in the C API would be implemented something like this:
// I must admit there is something freakishly 'hackish' about this sort of implementation (maintenance nightmare aside) - ther must be a better way?
// ExceptionInfo default ctor initialized to no error
void MyClass::foobarTrappedExceptionWrapper(ExceptionInfo& ei)
{
try {
// call foobar ...
foobar();
}
catch(fast_exception& fe)
{
switch (fe.errcode())
{
//package exception info into ei for C consumption
}
}
catch(std::exception &e)
{
//package exception info into ei for C consumption
}
}
Implementation of each of the C++ methods exposed in the C API needs to be enclosed in a try/catch statement (see above snippet). The performance implications for this seem quite serious (according to this article):
"It is a mistake (with high runtime
cost) to use C++ exception handling
for events that occur frequently, or
for events that are handled near the
point of detection."
At the same time, I remember reading somewhere in my C++ days, that all though exception handling is expensive, it only becmes expensive when an exception actually occurs. So, which is correct?. what to do?. Is there an alternative way that I can trap errors safely and pass the resulting error info to the C API?. Or is this a minor consideration (the article after all, is quite old, and hardware have improved a bit since then).
[Edit]
Removed question2, since I found a way to create a simple stack trace here.
Answers
Both are correct; you are misinterpreting the first source. The try{} block incurs basically no cost; it is the throw....catch (i.e. propagation) that is expensive. So, it's cheap if the exception doesn't occur, which is why they should not be used if they are occuring frequenty (because then you do throw...catch often).
Using a very long but fixed-size buffer isn't lighter weight than using an std::string. Using an std::string is a bad idea only if you are worried that you might throw an exception due to being out of memory (in which case the std::string constructor would throw because it cannot allocate space). However, why reinvent the wheel? I suggest you take a look at boost::exception, which provides a boost::exception class that allows arbitrary metadata to be attached to the exception object, and it can be as light weight (no metadata attached) or as heavy weight as you want, depending on what metadata you use.
Comment on Passing C++ Exceptions Around in C
The choice to inherit or not to inherit from std::exception has no implication on performance; the article was mentioning the fact that propagating an exception and performing stack unwinding is expensive (regardless of the exception's type). In terms of passing an exception around in the C world.... error handing in C is typically done using integer return types and error codes, although if you want to pass a C++ object around, as well, then if you can polymorphically copy the exception type, then you can simply construct a copy on the heap, and then pass around the exception object as type void*, and if you need to extract information from that object, then you can create C interfaces that are implemented in C++ and which cast the void* object back to a pointer to your exception type and extract the appropriate fields. An alternative, if all you want is the what() message, is to pass around the strdup() of the message. Bear in mind, though, that anything that requires allocation / copying is not going to work if std::bad_alloc is one of the exceptions your handling (in other words, if you can fail due to being out of memory, allocating more memory is not a good idea).
As the saying goes, "When in Rome, do as the Romans do".... my own advice would be to use return status codes and error codes when in C and to use exception handling in C++. I really would not bother trying to bring a C++ exception object into the C world. Also bear in mind, that it is more common for C++ code to call into C code than for C code to call into C++ code. If you are creating C interaces for your C++ code, then they should probably behave like C interfaces, namely returning error status codes. If your C++ code calls a C function that returns an error status code, then it is reasonable to throw an exception rather than returning an error status code where the underlying C code failed. In that case, though, you are in C++ space and don't really have to worry about the exception crossing back into C code. But, in the case where you do cross back into the C world, I would advise logging whatever information you have and using error status codes.
Also, given that std::exception::what() returns a char* object describing what happened, whereas your API returns an integer code indicating the type of exception... well, this will be really confusing to other people using your code. When I saw you use waht() in a switch statement, I was about to comment that you cannot switch on a string, and then had to make a double-take and realize it means something different than usual.