
#include "CrashSimulator.h"
#include <stdio.h>


class RAII
{
public:
	RAII(void)
	{
		printf("RAII constructor\r\n");
	}

	~RAII(void)
	{
		printf("RAII destructor\r\n");
	}
};


__declspec(noinline) void CrashSimulator::AccessViolation(void)
{
	RAII raii;

	// Live++: when running in the debugger, the debugger will catch the exception first.
	// continuing in the debugger will open Live++'s exception handler in the broker.
	//
	// in the exception handler in the broker, try the following things:
	//   *) "Disable instruction": this will disable the write instruction completely, so the code won't crash in the future.
	//      set a breakpoint in the code to verify that this function will still be entered, with the crashing instruction overwritten by a NOP.
	//   *) "Ignore instruction": this will ignore the instruction for now, but the code will crash again in the next frame.
	//   *) "Leave function": this will leave the function, unwinding the stack as demonstrated by the RAII instance.
	//   *) "Ignore exception": this will either return control to the debugger if one is attached, or exit the application.
	//
	// double-clicking a line in the shown call stack will open the corresponding source file.
	//
	// in addition to the functions offered by the exception handler, the code can of course also be fixed using Live++'s hot-reload.
	// this works no matter if the application is held by the debugger, or Live++'s exception handler is still active.
	int* address = reinterpret_cast<int*>(0x10);
	*address = 0xDEADC0DE;
}


__declspec(noinline) void CrashSimulator::DivideByZero(void)
{
	RAII raii;

	// Live++: once the access violation has been handled, the exception handler will catch the division by zero.
	// again, try the different things the exception handler has to offer, as described in AccessViolation().
	int a = 10;
	int b = 0;
	int result = a / b;
	printf("result: %d\n", result);
}
