C# code not catching SEHExceptions - c#

I have a C# application that invokes a managed C++ DLL that deliberately accesses to an invalid address; I enabled SEH Exceptions in my C++ project, I added a _se_translator_function into my C++ code and I also added a signal handler when a SIGSEGV occurs. Using my C++ code from a purely native test, everything works perfectly, but when I invoke my C++ code from a .net app, the app crashes with a:
Unhandled Exception: System.AccessViolationException: Attempted to
read or write protected memory. This is often an indication that other
memory is corrupt.
at K.killnative() in c:\users\ebascon\documents\visual studio 2013\projects\consoleapplication3\consoleapplication4\source.cpp:line 32
This is my C# console app:
namespace ConsoleApplication3 {
class Program {
static void Main(string[] args) {
try {
var k = new NativeKiller();
k.kill();
}
catch (Exception ex) {
Console.WriteLine("Catching " + ex);
}
}
}
}
and this is the C++/CLI code invoked:
void MXXExceptionTranslator(unsigned int, struct _EXCEPTION_POINTERS*)
{
throw std::exception("Crash happens");
}
void killnative() {
try {
_set_se_translator(MXXExceptionTranslator);
signal(SIGSEGV, [](int) {
puts("Exception");
exit(-1);
});
int* p = reinterpret_cast<int*>(0xDEADBEEF);
printf("%d\n", *p);
}
catch (...) { //Removing this catch does not change anything
puts("Doing nothing");
}
}
public ref class NativeKiller {
public:
void kill() {
killnative();
}
};
What do you think I am doing wrong? In my real world problem, I need this C++/CLI process (that is a bridge with a legacy app) to log an error message and die gracefully instead of popping the "The program stopped working" window.
Thanks in advance,
Ernesto

This is the good kind of problem to have, it helps you discover that you are not building your code correctly. The C++/CLI compiler is pretty powerful, almost too powerful, and can translate almost any native code into IL. The exact same kind of IL that a C# compiler generates. And it is treated the same at runtime, the jitter translates it to machine code at runtime.
This is not usually something you actually want. Native C or C++ code ought to be translated directly to machine code by the compiler. The MSDN article for _set_se_translator() does a decent job of warning about this:
When using _set_se_translator from managed code (code compiled with /clr) or mixed native and managed code, be aware that the translator affects exceptions generated in native code only. Any managed exceptions generated in managed code (such as when raising System::Exception) are not routed through the translator function.
The usual way to fall in the pit of success is by compiling the native code separately in its own source file or library project. But even easier is to take advantage of the C++/CLI compiler's ability to dynamically switch back-and-forth between IL and machine code generation in a single source file. Fix:
#pragma managed(push, off)
void MXXExceptionTranslator(unsigned int, struct _EXCEPTION_POINTERS*) { ... }
void killnative() { ... }
#pragma managed(pop)
public ref class NativeKiller { ... }
And you'll now see that the exception translator works fine.

Related

How do I catch a custom exception generated in a c++ dll on c#?

I'm creating a C++ DLL to be used in C#. This DLL throws exceptions whenever anything is wrong and the idea is to handle these in the C# code.
I created a new exception class in C++ inheriting from std::runtime_error because I not only need the what but also a numeric ID:
class insight_exception: public std::runtime_error
{
public:
explicit insight_exception(const int id, const std::string message):
std::runtime_error(message), id{id}
{}
virtual ~insight_exception() noexcept {}
const int id;
};
Whenever something goes wrong in the C++ code I do this:
throw insight_exception(103, "size Pointer is NULL");
I have a little example in C# to "exercise" the DLL, just to test it before sending it to our C# developer, and when I execute the little C# program I can verify that the DLL is throwing the exceptions because I'm getting this:
terminate called after throwing an instance of 'insight_exception'
My problem is that I don't know any C# and I don't really know to "import" the insight_exception class into C# so I can catch it.
Solutions like this post don't help because they assume you can use the class by using a function like this:
insight_exception* create_insight_exception()
{
return new insight_exception();
}
And I can't do that because I need something like this in C#
try
{
}
catch (insight_exception e)
{
}
So I can't create the class like:
IntPtr insight_exception = create_insight_exception();
One important thing to know is that I'm creating the DLL on Linux by cross-compiling using MinGW, so I can't do #include <Windows.h> or any other windows-related includes or imports when creating the DLL. I don't really use Windows but only for my little test C# code.
EDIT:
Thanks to a comment, I looked into the following questions:
C# not catching unhandled exceptions from unmanaged C++ dll
This one looks promising but the problem is that the answer suggest a compilation done in Windows. I tried to add the /EHa compilation flag equivalent in GCC (-funwind-tables) but that doesn't help. I still can't catch the exception using catch (SEHException ex) nor catch (Exception ex) in the C# code.
Can you catch a native exception in C# code?
Suggests using Win32Exception but that doesn't work either. I can't catch the exception with catch (Win32Exception ex) in the C# code.

How to catch an AccessViolationException in C# from a C++ dll which is wrapped in a C# dll using SWIG

I am using a function from an auto generated C# dll in my C# code. The auto generated C# dll is a wrapper for a C++ dll, I think the code is mostly auto generated with SWIG, but I don't know more about it. I think it basically just wraps the C++ functions using PINVOKE (but I am not sure how the SWIG stuff works).
The problem is that I can not catch an exception, when it occurs in the C++ dll. In my Case the frame() method throws an AccessViolationException, but I can not catch it with a try catch block. Does SWIG provides some sort of exception handling for C#? I just want to prevent my application crash.
The function from the wrapper dll (C#):
public virtual void frame() {
osgViewerPINVOKE.ViewerBase_frame(swigCPtr);
}
The C++ Code:
SWIGEXPORT void SWIGSTDCALL CSharp_ViewerBase_frame(void * jarg1) {
osgViewer::ViewerBase *arg1 = (osgViewer::ViewerBase *) 0 ;
arg1 = (osgViewer::ViewerBase *)jarg1;
(arg1)->frame();
}
My C# code, where I want to catch exceptions:
try
{
this.viewer.frame();
}
catch (AccessViolationException exception)
{
Console.WriteLine(exception);
}
I have read this article from SWIG: http://www.swig.org/Doc1.3/CSharp.html#csharp_exceptions
But I do not understand much of it. Do I need to edit the C++ dll? Because this is no option for me. I could only modify the wrapper class, but I would prefer not to do so.

How to call a throwing C# function from C++ in a C# app such that the C++ stack is unwound properly?

Is it possible to call a throwing C# function from a C++ call in a C# app such that the C++ stack is unwound properly? Is there any documentation of this?
For example, please consider this C# code:
using System;
public class Test
{
public static void CalledFromCpp()
{
throw new Exception("Is this safe? Is C++ stack unwound properly?");
}
public static void Main()
{
try {
CppFunc(CalledFromCpp);
}
catch(Exception e)
{
Console.Writeline("Exception e: {0}", e);
}
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void CsFuncToBeCalledFromCpp();
[DllImport("CppApp", CallingConvention = CallingConvention.Cdecl)]
private static extern void
CppFunc(CsFuncToBeCalledFromCpp callback);
}
Along with this C++ code:
void CppFunc(void (*handler))
{
SomeResourceWrappingClass releasesResourceOnDestruction();
handler();
}
I tried this out, and the C# exception was caught successfully, but releasesResourceOnDestruction didn't have it's destructor called. This seems to indicate that the C++ stack is not being unwound properly -- is it possible to get it to unwind properly here? Is there any documentation on this behavior?
For context: I want to sometimes trigger a C# exception from C++ code if possible, so that I don't need every call from C# into C++ have to check something afterwards to see if a C# exception needs to be thrown.
Try enabling Structured Exception Handling in your C++ project (Project Properties -> C/C++ -> Code Generation -> Enable C++ Exceptions -> "Yes with SEH Exceptions (/EHa)"). Without SEH exceptions, the exception that is returned to the C++ layer does not have enough information to unwind the stack properly.

Handling errors while using unmanaged code in a managed one ( C++, C, C++/CLI, C#)

I am using a badly written 3rd party (C/C++) Api. I used it from managed code( C++/ CLI). Get sometimes "access violation errors". And this crash whole application. I know i can not handle those errors[ what can i do if a pointer acess to illegal memory location etc].
But I do not want my application crash as a whole. At least if there is a real problem, my application gracefully should say "OK.I can not do my job.BYE. " :-) then it least execute some alternative scenarious and finally close itself.
But there seems to be no way, to catch( may be wrong term, the rigth word may be to be informed about) access violation and similiar errors.Is there a way to be informed about those errors. So i can execute my alternative scenarious.
PS: Standard Exception handling does not solve this.
#include "stdafx.h"
#include <iostream>
using namespace System;
using namespace std;
static void ThrowingManagedException()
{
throw gcnew ArgumentException("For no good reason");
}
static void ThrowingNativeException()
{
throw std::exception("For no good reason");
}
static void SomeBadThingsHappen()
{
short a[1];
a[0]=1;
a[2]= 2; // SomeOne make stupid mistake
}
int main(array<System::String ^> ^args)
{
Console::WriteLine(L"Test Exceptions");
try
{
SomeBadThingsHappen();
//ThrowingNativeException();
//ThrowingManagedException();
}
catch(Exception^ e)
{
Console::WriteLine("Something awful happened: "+ e);
}
Console::WriteLine("Press enter to exit");
Console::Read();
return 0;
}
If you're sure that the problems are bugs in the library, and not a result of you passing in bad arguments, then your most robust option is inter-process communication with a hosting process that loads the library. That way your OS process separation keeps the library from bringing down your application.
You can try to catch access violations in-process, using SEH, but if the library writes to wild pointers and not simple null pointers, then the process won't survive even with an exception handler.
Your example will not cause an access violation, it's a buffer overrun of a buffer on the stack, so the adjacent memory location contains some other valid data which gets stomped on.

Deleting an unmanaged object from Finalize throws an AccessViolationException

I'm writing a wrapper library using C++/CLI for an unmanaged C++ project. The goal is to expose this library to C# applications. Here's what I have so far.
#pragma once
#include "Settings.h"
#include "Settings/SettingsPrivate.h"
public ref class Settings
{
public:
Settings();
virtual ~Settings();
protected:
!Settings();
public:
unsigned char GetModel(int iNumber);
private:
CSettings* m_pSettings;
};
#include "stdafx.h"
#include "Managed/Settings.h"
Settings::Settings()
{
// Pointer to unmanaged object
m_pSettings = new CSettings();
}
Settings::~Settings()
{
this->!Settings();
}
Settings::!Settings()
{
if (m_pSettings)
{
delete m_pSettings;
m_pSettings = NULL;
}
}
unsigned char Settings::GetModel(int iNumber)
{
return m_pSettingss->GetModel(iNumber);
}
The code executes fine in the test application I wrote. The function call succeeds. The problem is that when the GC Finalizes this object, it throws an exception.
An unhandled exception of type 'System.AccessViolationException' occurred in Wrapper.dll
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I can't see any obvious reason why this exception is being thrown. I tried disposing of the object explicitly by calling Dispose from my C# application. It still throws the same exception.
Here's the test application:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WrapperTest
{
class Program
{
static void Main(string[] args)
{
Settings settings = new Settings();
byte b = settings.GetModel(0);
settings.Dispose();
return;
}
}
}
Would someone point out what I'm doing wrong??
It was a project configuration error. The code actually ran fine in Release mode.
In debug mode I linked in some release DLL's when I should have been statically linking against debug libraries. Why this caused memory corruption I haven't yet investigated but it has solved the problem.
Otherwise the code posted above is correct.
You should enable more verbose heap debugging functionality. I tested your code and it did not fail for me. I had to use malloc/free instead of new/delete as you didnt define CSettings, however the effect should be the same.
I added this to make sure I had enough heap churn to trigger a failure if their was any corruption;
unsigned char Settings::GetModel(int iNumber)
{
for(int i=0; i < iNumber; i++)
free(malloc(1024));
return iNumber;
}
For me your code worked with no failure. You should look into some of your compilation settings, are you linking to an external library for CSettings? If so you need to make sure the CRT is the same version, etc. Also you know you have to use one of the DLL run time's not /MT or /MTd.

Categories

Resources