www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How can I get a backtrace when my WndProc throws?

reply Markus <fmmbj protonmail.com> writes:
Hi, I'm using core.sys.windows.windows to make a Windows GUI, and 
the WindowProc must be nothrow. My code does not provide me a 
stack backtrace when some exception is thrown in there. I would 
like to have at least the number of the line that caused a throw, 
has anyone an idea how to do this? Thanks for reading.

Below is the code for the Windows application. I guess I need to 
improve window_procedure_nothrow() somehow.

import std;
import core.sys.windows.windows;

HWND main_window;

LRESULT window_procedure(
     HWND hwnd,
     uint msg,
     WPARAM wparam,
     LPARAM lparam)
{
	if(msg == WM_CLOSE)
	{
		PostQuitMessage(0);
		return 0;
	}
	
	if(msg == WM_KEYDOWN)
	{
		format("%d", 0.5); // trigger an exception

		format("%d", 0.7);
	}
	
	return DefWindowProc(hwnd, msg, wparam, lparam);	
}

extern(Windows) LRESULT window_procedure_nothrow(
     HWND hwnd,
     uint msg,
     WPARAM wparam,
     LPARAM lparam) nothrow
{
	// this prints only a line number from within this function
	// and some stack backtrace of functions outside the window 
procedure
	if(0)
	{
		return assumeWontThrow(window_procedure(hwnd, msg, wparam, 
lparam));
	}

	// this prints no line number at all
	// can get only the exception message from 
collectException().msg	
	if(1)
	{
		LRESULT result;
		auto ce = collectException(
			window_procedure(hwnd, msg, wparam, lparam),
			result);
		if(ce !is null)
		{
			assumeWontThrow(writeln(ce.msg));
			TerminateProcess(GetCurrentProcess(), 0);
		}
		return result;
	}
}

void main()
{
	WNDCLASSEX wndclassex = {
		style: 0,
		lpfnWndProc: &window_procedure_nothrow,
		lpszClassName: "a",
		hInstance: GetModuleHandle(null),
		hIcon: LoadIcon(null, MAKEINTRESOURCE(32517)),
		hCursor: LoadCursor(null, MAKEINTRESOURCE(32512)) };

	ATOM windowclass = RegisterClassEx(&wndclassex);
	assert(windowclass != 0);

	main_window = CreateWindowEx(
		0,
		"a",
		"test",
		WS_OVERLAPPEDWINDOW | WS_VISIBLE,
		100,
		100,
		200,
		200,
		null,
		null,
		GetModuleHandle(null),
		null);
	assert(main_window != null);

	for(;;)
	{
		MSG msg;
		int ret = GetMessage(&msg, null, 0, 0);

		if(ret == 0) break;

		assert(ret != -1);

		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
}
Jun 03 2019
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 3 June 2019 at 11:19:22 UTC, Markus wrote:
 a throw, has anyone an idea how to do this?
First thing I'd try is to just print the exception when you catch it. The toString method can do a backtrace. Don't use just e.msg, that's just the string the constructor sent, use e.toString and see if it works for you.
Jun 03 2019
parent Markus <fmmbj protonmail.com> writes:
On Monday, 3 June 2019 at 12:09:18 UTC, Adam D. Ruppe wrote:

 Don't use just e.msg, that's just the string the constructor 
 sent, use e.toString and see if it works for you.
toString works, thanks! :)
Jun 03 2019