I've compiled LuaJIT with MSVC x64, which means that there should be full C++ exception interoperability, according to the official LuaJIT website.
One of the points states that "Throwing Lua errors across C++ frames is safe. C++ destructors will be called."
I assumed that this means I can use lua_error in a C++ function and not worry about objects on the stack:
struct Test
{
Test() {std::cout<<"Constructor"<<std::endl;}
~Test() {std::cout<<"Destructor"<<std::endl;}
};
int some_function(lua_State *l)
{
Test t {};
lua_pushstring(l,"error message");
lua_error(l);
return 0;
}
(The function is called from within a Lua-script)
However, the destructor is never called. So what does that point on the website actually mean? How can I use lua_error without having to worry about memory leaks?
According to this question, the problem can be solved by compiling Lua as C++-code, but since I'm using LuaJIT, I'm not sure if that won't cause me any problems?
Related
I am writing a program using mixing c and c++, and I meet a problem about object destruction in c++ exception handler. I wrote a simple case to reproduce the problem.
main.cpp
#include <iostream>
extern "C" void test(void(*f)(void));
struct foo {
~foo() {
std::cout << "foo destruction" << std::endl;
}
};
void error_handler(void) {
throw 1;
}
int main() {
try {
foo f;
test(error_handler);
} catch (...) {
}
}
test.c
void test(void(*handler)(void)) {
handler();
}
When I build this in Visual Studio 2015 and Visual Studio 2017, the foo's destructor was not called. But when I test it using gcc 5.4, the foo's destructor works fine.
Is it possible to throw C++ exception in C code through calling function pointer (which pointer to the function implemented in cpp code)? Is the code above illegal or it's just an msvc bug?
The Windows Exception mechanism is explicitly designed to be able to run destructors and perform finally type cleanup even in the presence of exceptions and similar from other languages.
So what you're asking should work fine on windows - its what its designed to do.
However, you need to explicitly enable this in Visual Studio. By default, visual studio sets up C++ code with /EHsc exception model which explicitly assume that extern "C" functions do not throw or pass through exceptions. This is an optimisation, and generally a good one.
However, if you need to assume that extern "C" functions do throw or pass through exceptions then you need to change your exception model. You probably want /EHs.
However, I'd recommend reading up on the ramifications of this before you change it here.
Edit: Whether to use this functionality or not is debatable. Generally with exceptions (and other similar mechanisms) all code on the stack between the thrower and caller need to be exception safe. If you own the code then this is fine, if there's things like windows callbacks or other libraries on the stack then you need to find a guarantee that this is ok. And in general for windows internal code its not.
Throwing exceptions across language boundaries always leaves program in inconsistent state. Stack unwinding performed in case of C++ exception thrown is guaranteed to work only on (binary compatible) C++ stack frames. C language does not even have a concept of exceptions. Even if stack unwinding manages to unwind C stack frames it will not perform any cleanup for them. So any callback function passed to C code should be declared as noexcept and handle error in some manner that does not involve throwing of exception across language boundary:
void error_handler(void) noexcept {
try
{
throw 1;
}
catch(…)
{
// TODO convert to error code or store for later using exception_ptr
}
}
C++ class constructor can be inlined or not be inlined. However, I found a strange situation where only inline class constructor can avoid Visual Studio memory crash. The example is as follows:
dll.h
class _declspec(dllexport) Image
{
public:
Image();
virtual ~Image();
};
class _declspec(dllexport) Testimage:public Image
{
public:
Testimage();
virtual ~Testimage();
};
typedef std::auto_ptr<Testimage> TestimagePtr;
dll.cpp
#include "dll.h"
#include <assert.h>
Image::~Image()
{
std::cout<<"Image is being deleted."<<std::endl;
}
Image::Image()
{
}
Testimage::Testimage()
{
}
Testimage::~Testimage()
{
std::cout<<"Geoimage is being deleted."<<std::endl;
}
The dll library is compiled as a dynamic library, and it is statically linked to the C++ runtime library (Multi-threaded Debug (/MTd)). The executable program that runs the library is as follows:
int main()
{
TestimagePtr my_img(new Testimage());
return 0;
}
The executable program will invoke the dll library and it also statically links the runtime library. The problem I have is that when running the executable program the following error message appears:
However, when the class constructor in dll is inlined as the following codes show:
class _declspec(dllexport) Image
{
public:
Image();
virtual ~Image();
};
class _declspec(dllexport) Testimage:public Image
{
public:
Testimage()
{
}
virtual ~Testimage();
};
The crash will disappear. Could someone explain the reason behind? Thanks! By the way, I am using VC2010.
EDIT: The following situation also trigger the same crash
.
Situation 1
int main()
{
//TestimagePtr my_img(new Testimage());
Testimage *p_img;
p_img = new Testimage();
delete p_img;
return 0;
}
it is statically linked to the C++ runtime library (Multi-threaded Debug (/MTd)
This is a very problematic scenario in versions of Visual Studio prior to VS2012. The issue is that you have more than one version of the CRT loaded in your process. One used by your EXE, another used by the DLL. This can cause many subtle problems, and not so subtle problems like this crash.
The CRT has global state, stuff like errno and strtok() cannot work properly when that global state is updated by one copy of the CRT and read back by another copy. Relevant to your crash, a hidden global state variable is the heap that the CRT uses to allocate memory from. Functions like malloc() and ::operator new use that heap.
This goes wrong when objects are allocated by one copy of the CRT and released by another. The pointer that's passed to free() or ::operator delete belongs to the wrong heap. What happens next depends on your operating system. A silent memory leak in XP. In Vista and up, you program runs with the debug version of the memory manager enabled. Which triggers a breakpoint when you have a debugger attached to your process to tell you that there's a problem with the pointer. The dialog in your screenshot is the result. It isn't otherwise very clear to me how inlining the constructor could make a difference, the fundamental issue however is that your code invokes undefined behavior. Which has a knack for producing random outcomes.
There are two approaches available to solve this problem. The first one is the simple one, just build both your EXE and your DLL project with the /MD compile option instead. This selects the DLL version of the CRT. It is now shared by both modules and you'll only have a single copy of the CRT in your process. So there is no longer a problem with having one module allocating and another module releasing memory, the same heap is used.
This will work fine to solve your problem but can still become an issue later. A DLL tends to live a life of its own and may some day be used by another EXE that was built with a different version of the CRT. The CRT will now again not be shared since they'll use different versions of the DLL, invoking the exact same failure mode you are seeing today.
The only way to guarantee that this cannot happen is to design your DLL interface carefully. And ensure that there will never be a case where the DLL allocates memory that the client code needs to release. That requires giving up on a lot of C++ goodies. You for example can never write a function that returns a C++ object, like std::string. And you can never allow an exception to cross the module boundary. You are basically down to a C-style interface. Note how COM addresses this problem by using interface-based programming techniques and a class factory plus reference counting to solve the memory management problem.
VS2012 has a counter-measure against this problem, it has a CRT version that allocates from the default process heap. Which solves this particular problem, not otherwise a workaround for the global state issue for other runtime functions. And adds some new problems, a DLL compiled with /MT that gets unloaded that doesn't release all of its allocations now causes an unpluggable leak for example.
This is an ugly problem in C++, the language fundamentally misses an ABI specification that addresses problems like this. The notion of modules is entirely missing from the language specification. Being worked on today but not yet completed. Not simple to do, it is solved in other languages like Java and the .NET languages by specifying a virtual machine, providing a runtime environment where memory management is centralized. Not the kind of runtime environment that excites C++ programmers.
I tried to reproduce your problem in VC2010 and it doesn't crash. It works with a constructor inline or not. Your problem is probably not in what you write here.
Your project is too hard to open as it seams to have its file pathes set in absolute, probably because generated with CMake. (So the files are not found by the compiler).
The problem I see in your code is that you declare the exported classes with _declspec(dllexport) directly written.
You should have a #Define to do this, and the value should be _declspec(dllimport) when read from the exe compilation. Maybe the problem comes from that.
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. 😃
Background: We are using Keil to compile our NXP LPC2458 project. There are numerous tasks that are being run on Keil’s RealView RTOS. There is stack space created, which is being allocated to each task. There is no HEAP created by default, and I want to avoid it since we can't afford the code-space overhead and the cost of "garbage collecting"
Objective: Use C++ in the embedded code without using the heap. Keil provides the #pragma (__use_no_heap) which prevents malloc() and free() calls to be linked.
Solution: I tried creating a Singleton with a private static pointer. My hopes were that the new() would not be called since I declared dlmData as static in the getDLMData(). For some reason, the linker still states that malloc() and free() are being called. I have thoughts of a private operator new () and a private operator delete() , and then declaring the dlmData as static within the overloaded function. It is not working for some reason. WHAT AM I DOING WRONG?
//class declaration
class DataLogMaintenanceData
{
public:
static DataLogMaintenanceData* getDLMData();
~DataLogMaintenanceData()
{ instanceFlag = FALSE; }
protected:
DataLogMaintenaceData(); //constructor declared protected to avoid poly
private:
static Boolean instanceFlag;
static DataLogMaintenceData *DLMData;
}
//set these to NULL when the code is first started
Boolean DataLogMaintenanceData::instanceFlag = FALSE;
DataLogMaintenanceData *DataLogMaintenaceData::DLMData = NULL;
//class functions
DataLogMaintenanceData *DataLogMaintenanceData::getDLMData()
{
if (FALSE == instanceFlag)
{
static DataLogMaintenanceData dlmData;
DLMData = &dlmData;
instanceFlag = TRUE;
return DLMData;
}
else
{
return DLMData;
}
}
void InitDataLog ( void )
{
DataLogMaintenanceData *dlmData;
dlmData = DataLogMaintenanceData::getDLMData();
// to avoid dlmData warning
dlmData = dlmData;
}
//ACTUAL TASK
__task DataLog()
{
.. .. .. code to initialize stuff
InitDataLog();
.. .. ..more stuff
}
For some reason, the only way I can get this to compile, is to create a heap space and then allow the malloc() and free() calls to be compiled into the project. As expected, the “static”ally defined object, dlmData, resides in the RAM space allocated to the dataLog.o module (i.e. it doesn’t live in the HEAP).
I can’t figure out, and I have checked Google, what am I missing? Is it possible in C++ to bypass malloc() and free() when compiling pure objects? I know I can replace the RTOS’s implementation of malloc() and free() to do nothing, but I want to avoid compiling in code that I won’t use.
Probably some of the code we aren't seeing calls a function that calls malloc behind the scenes.
From http://www.keil.com/support/man/docs/armlib/armlib_CJAIJCJI.htm you can use --verbose --list=out.txt on the link line to get details about the malloc caller.
Included in the Keil installation is a set of PDFs... one of the documents (document ID DUI0475A) is titled "Using ARM C and C++ Libraries and Floating-Point Support". It discusses use of the heap (and preventing its use) in several places.
Specifically, check out section 2.64 "Avoiding the ARM-supplied heap and heap-using library functions", lots of good information there. The interesting text in that section:
You can reference the __use_no_heap or __use_no_heap_region symbols in
your code to guarantee that no heap-using functions are linked in from
the ARM library.
__use_no_heap guards against the use of malloc(), realloc(), free(),
and any function that uses those functions. For example, calloc() and
other stdio functions.
__use_no_heap_region has the same properties as __use_no_heap, but in
addition, guards against other things that use the heap memory region.
For example, if you declare main() as a function taking arguments, the
heap region is used for collecting argc and argv.
Since your question is about how prevent malloc() from being called / used, that might put you on the right track.
From the code you've posted I cannot see anything that would like to allocate the memory on the heap. Are there any implicit conversions taking place somewhere? What if you compile without this class at all?
What you could do:
1) Run under debugger (assuming you can build a runnable image, maybe on an emulator), set a breakpoint in malloc and examine the stack
2) Provide your own malloc and free to make linker happy, then repeat step 1.
You may find that you need to link against a different version of C runtime startup. In the worst case if number of calls to malloc/free is limited you can roll out your own version which will give the callers some preallocated memory - but hopefully this will not be neccessary.
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.