Here's the scenario I am confronted with:
in a simple DLL, written in C, there are functions which access files, for example:
DLL_EXPORT void Virt_Hello(void) {
FILE *f = fopen("Hello_world", "w");
if (f) {
fprintf(f, "Hello world!\n");
}
fclose(f);
}
in the managed code:
[SuppressUnmanagedCodeSecurity]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void Virt_HelloDelegate();
private IntPtr m_helloPtr;
m_helloPtr = GetProcAddress(m_libraryPtr, "Virt_Hello");
Virt_Hello = Virt_HelloDelegate)Marshal.GetDelegateForFunctionPointer(m_helloPtr, typeof(Virt_HelloDelegate));
and later, this function is called as:
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
public void Hello()
{
Virt_Hello();
}
I've been reading for the last couple of days pretty much everything I could find on this topic however it still doesn't work: the file is not open, and the calling managed code/process just hangs - no exceptions are thrown either.
Tried StdCall calling convention, changed several parameters on the SecurityPermission attribute - to no avail. I've even made sure all assembly dependencies are signed.
Of course I would prefer to integrate it through C++/CLI instead of PInvoke-ing however the DLL is a blackbox for me.
Any help or suggestion how to go forward would be much appreciated.
I'm pretty sure I'm missing something obvious but right now I just can't see it.
My best regards to the community!
I’ve compiled libsass 3.3.6 into a DLL with VS 2015 using the included solution files. Running the code below causes the program to crash immediately with no output.
using System;
using System.Runtime.InteropServices;
namespace Sass.Cli {
static class Sass {
[DllImport(#"C:\...\libsass\win\bin\libsass.dll")]
public static extern String libsass_version();
}
class Program {
static void Main(string[] args) {
Console.WriteLine(Sass.libsass_version());
}
}
}
The source for the invoked function is at sass.cpp:61.
const char* ADDCALL libsass_version(void)
Both the DLL and the above code were compiled for x86. Running the VS debugger on crash gives me the following exception: Unhandled exception at 0x771A9841 (ntdll.dll) in Sass.Cli.exe: 0xC0000374: A heap has been corrupted (parameters: 0x771DC8D0).
Is this something that can be fixed or that I’ve overlooked? Or is it just the case that libsass DLLs aren’t currently working?
When a string is used as a return type then the framework assumes it was allocated by calling CoTaskMemAlloc. It then copies the content of the string and deallocation by calling CoTaskMemFree. That is the explanation for your error.
Solve it by changing the return value to IntPtr and getting the string content with Marshal.PtrToStringAnsi. You won't need to deal located anything since this version string will be static.
I can't tell what the calling convention is. You should check the code and docs to find out. Still, this function is so simple that it behaves the same way for both cdecl and stdcall so that can't explain the error. Still, you will need to get it right for the rest of the library.
Note that I am guessing a little here. You've not provided full details. You should consult the code and docs to double check my guesswork.
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.
I want to test if my application crash dump can be debugged. But firstly, I need to generate a crash dump of my application. I'm using C# to code my app, and have tried with many exceptions and unsafe code etc. but don't get it.
Thanks!
Edit: Sorry, Just forgot something, I'm making the application with Unity3D, which handles exceptions for me automatically.
Edit 2: Thanks all for your answers. I've tested your suggestions in a standard C# application and it all works fine, but not in my Unity3D application (written with C#). It seems like Unity3D requires more effort to cause a crash, I might email Unity3D to get a answer. I will post here if I get it. Cheers!
The following will provide an unhandled exception and will ask for you to choose a debugger:
System.Diagnostics.Debugger.Launch()
StackOverflowException is a badass:
void PerformOverflow()
{
PerformOverflow();
}
Usage:
PerformOverflow();
Throw an exception :)
throw new Exception("Your exception here!");
For C# in Unity3D
There is UnityEngine.Diagnostics.Utils.ForceCrash (in Unity 2018.3)
This can be used with one of the following ForcedCrashCategory enum parameter:
AccessViolation
Cause a crash by performing an invalid memory
access.The invalid memory access is performed on each platform as
follows:
FatalError
Cause a crash using Unity's native fatal error
implementation.
Abort
Cause a crash by calling the abort() function.
PureVirtualFunction
Cause a crash by calling a pure virtual function
to raise an exception.
For older versions of Unity:
UnityEngine.Application.ForceCrash(int mode)
For even older versions (Unity 5):
UnityEngine.Application.CommitSuicide(int mode)
From my experience, mode 0 causes a "unity handled" crash (where the Unity crash dialog appears), and mode 2 causes a "hard" crash where the Windows error dialog appears.
This seems consistent with this post by Smilediver on mode:
0 - will simulate crash, 1 - will simulate a fatal error that Unity
has caught, 2 - will call abort().
(These methods are not documented as they were intended for Unity's internal use. They may also be marked [Obsolete] depending on your Unity version.)
Well. The only good 100% way actualy crash CLR is to inject a native exception into the managed world.
Calling the Kernel32.dll's RaiseException() directly will immediately crash ANY C# application, and Unity Editor as well.
[DllImport("kernel32.dll")]
static extern void RaiseException(uint dwExceptionCode, uint dwExceptionFlags, uint nNumberOfArguments, IntPtr lpArguments);
void start()
{
RaiseException(13, 0, 0, new IntPtr(1));
}
Happy crashing. Please note that in order to debug native and managed, you will need two instances of Visual Studio running. If you are developing native P/INVOKE plugin, set up it that Visual Studio Instance 1 is native debugger and uses Unity or your C# program as a Host program, and you attach to the Host program from another Visual Studio Instance.
Another option is to call
System.Environment.FailFast("Error happened")
A surefire way to do it is as follows:
ThreadPool.QueueUserWorkItem(new WaitCallback(ignored =>
{
throw new Exception();
}));
All the others can be handled by the top level ApplicationDomain.OnUnhandledException and the like.
This one will kill it dead (assuming .NET 2.0+, and not using 'legacyUnhandledExceptionPolicy': http://msdn.microsoft.com/en-us/library/ms228965.aspx).
None of the answers crashed my app the way I was looking for. So here is the approach that worked for me.
private void Form1_Load(object sender, EventArgs e)
{
object p = 0;
IntPtr pnt = (IntPtr)0x123456789;
Marshal.StructureToPtr(p, pnt, false);
}
public void Loop()
{
Loop();
}
//call this
Loop();
I think there was a code in earlier unity versions like
Application.commitSuicide(number Input);
Now it is replaced by
Application.ForceCrash(number input);
Till this point, I dont know what different numbers do in number input, but for me,
Application.ForceCrash(1);
does the job.
you could also divide by zero,
z = 0;
int divide = 1 / x;
int[] x = {0};
int blah = x[2];
will cause an exception just as well
It's easy enough to reproduce if you try to transform a null game object. For example, like this:
public static GameObject gameObjectCrash;
public void GenerateCrash()
{
gameObjectCrash.transform.rotation = Quaternion.Euler(90, 0, 0);
}
Use below code to close the application.
Environment.Exit(1);
Exit needs a parameter called exitcode. If exitcode=0 means there was no error. Supply a non-zero exit code to to reflect an error.
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.