Day 2 - using VS 2013 for editing/building, not CL

Hey gang,
I'm loving this series, I'm a game designer who has decided to get his hands dirty (sooo dirty) in c++ and I like to tinker with stuff so I decoded to try using vs2013 as a complete solution, as opposed to just the debugger.

But I've hit an issue: Day 2 win32_handmade.cpp compiles and links just fine in VS, BUT when I go to debug it I get a breakpoint because:
1
HEAP[handmadehero.exe]: Heap block at 00D24AF8 modified at 00D24B19 past requested size of 19


So investigated further and it seems to trigger this just before it reaches the if(WindowHandle) section of the code. WindowHandle in the watch window says 0xcccccccc {unused=???} and when I expand the arrow I get 'unable to read memory'.

Am I just painting myself into a corner using VS2013 on win8.1?

I've attached my whole cpp file for those interested.

Thanks!

Edited by Dana Fortier on Reason: added file oops
You have not added cpp file.
Sorry, it wouldn't let me attach apparently.

Here it is:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <windows.h>

// define the windows callback messaging responses
LRESULT CALLBACK MainWindowCallback( HWND Window,UINT Message,WPARAM WParam,LPARAM LParam)	
{

	LRESULT Result = 0;

	switch(Message)
	{
	case WM_SIZE:
		{
			// use of block is to prevent var scope leak
			OutputDebugStringA("WM_SIZE\n");
		}break;
	case WM_PAINT:
	{
		PAINTSTRUCT Paint;
		HDC DeviceContext = BeginPaint(Window, &Paint);
		int X = Paint.rcPaint.left;
		int Y = Paint.rcPaint.top;
		int Height = Paint.rcPaint.bottom - Paint.rcPaint.top;
		int Width = Paint.rcPaint.right - Paint.rcPaint.left;
		static DWORD Operation = WHITENESS;
		PatBlt(DeviceContext, X, Y, Width, Height, Operation);
		if (Operation == WHITENESS)
		{
			Operation = BLACKNESS;
		}
		else
		{
			Operation = WHITENESS;
		}
		EndPaint(Window, &Paint);


		
		
		OutputDebugStringA("WM_SIZE\n");
	}break;

		case WM_DESTROY:
		{
			PostQuitMessage(0);
			OutputDebugStringA("PostQuitMessage(0) - WM_DESTROY\n");
		}break;

		case WM_CLOSE:
		{
			PostQuitMessage(0);
			OutputDebugStringA("WM_CLOSE\n");
		}break;

		case WM_ACTIVATEAPP: //let's us know if user has clicked and made the window active
		{
			OutputDebugStringA("WM_ACTIVATEAPP\n");
		}break;

		default:
		{
		//	OutputDebugStringA("Default case!\n");
			//this is the catchall LRESULT return to windows, there's a default Windows way to do this
			Result = DefWindowProc(Window, Message, WParam, LParam);
		}break;
	}

	return(Result);

}

// main program entry!
int CALLBACK WinMain(
	HINSTANCE Instance,
	HINSTANCE PrevInstance,
	LPSTR     CmdLine,
	int       CmdShow
	)
{
	// create instance of windowclass and initialize to 0/null
	WNDCLASS WindowClass = {};
	
	//define the window class fields
	//WindowClass.style = CS_OWNDC|CS_HREDRAW|CS_VREDRAW;
	WindowClass.lpfnWndProc = MainWindowCallback; //how window responds to events by passing in a function via pointer, defined above
	WindowClass.hInstance = Instance; // get the windowhandle instance
	//HICON     hIcon; //may be used later
	WindowClass.lpszClassName = "HandMadeHeroWindowClass";

	//MessageBox(0, "This is handmade hero!", "handmade caption", MB_OK | MB_ICONINFORMATION);

	//REGISTERING THE WINDOW CLASS
	
	if (RegisterClassA(&WindowClass))
	{
		HWND WindowHandle = CreateWindowExA(
			0, // extended style, no thanks
			WindowClass.lpszClassName,
			"Handmadehero!",
			WS_VISIBLE | WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			0,
			0,
			Instance,
			0);
		
		if (WindowHandle)
		{
			
			
			for (;;)
			{
				MSG Message;
				BOOL bMessageResult = GetMessage(&Message, 0, 0, 0);
				
				if (bMessageResult > 0)
				{
					TranslateMessage(&Message);
					DispatchMessage(&Message);
				}
				else
				{
					break;
				}

			}

		}
		else 
		{
			//*TODO: WindowHandle non-existent Log it!
			OutputDebugStringA("WindowHandle non-existent ");
		}
	}
	
	else 
	{
		//*TODO: RegisterClass(&WindowClass) is bad Log it!
		OutputDebugStringA("RegisterClass(&WindowClass) is bad ");
	}
	
	return(0);
}
This code does not trigger breakpoint for me. Not in 32-bit, not in 64-bit mode.
What place does it trigger for you? What is visible in callstack when it stops in the debugger?
It triggers right after stepping out of RegisterClassA(&WindowClass).

This is the callstack:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
>	ntdll.dll!_RtlpBreakPointHeap@4()	Unknown
 	ntdll.dll!_RtlpCheckBusyBlockTail@8()	Unknown
 	ntdll.dll!RtlpValidateHeapEntry()	Unknown
 	ntdll.dll!_RtlDebugFreeHeap@12()	Unknown
 	ntdll.dll!RtlpFreeHeap()	Unknown
 	ntdll.dll!RtlFreeHeap()	Unknown
 	KernelBase.dll!_GlobalFree@4()	Unknown
 	kernel32.dll!GlobalFreeStub()	Unknown
 	AppProfiles.dll!667d0199()	Unknown
 	[Frames below may be incorrect and/or missing, no symbols loaded for AppProfiles.dll]	
 	AppProfiles.dll!667c181e()	Unknown
 	AppProfiles.dll!667dafb0()	Unknown
 	AppProfiles.dll!667dcf0c()	Unknown
 	AppProfiles.dll!667c191c()	Unknown
 	user32.dll!_DispatchHookW@16()	Unknown
 	user32.dll!__fnHkINLPCBTCREATESTRUCT()	Unknown
 	ntdll.dll!_KiUserCallbackDispatcher@12()	Unknown
 	kernel32.dll!@BaseThreadInitThunk@12()	Unknown
 	ntdll.dll!__RtlUserThreadStart()	Unknown
 	ntdll.dll!__RtlUserThreadStart@8()	Unknown
Oh, that's interesting, I quickly created an x64 config and that seems to have worked. Except now my window title is in some sort of asian symbol writing. However win32 still breaks with the same call stack...

Edit: setting the project to character type-> multibyte seems to have done the trick!

Edited by Dana Fortier on Reason: clarity
I think the reason is that, since its the Unicode that messed it up, remember the function you are calling is the ANSI version, hence the "a" at the end of the function name. I think its because its expecting the class name to be in ANSI, but when you have the project in unicode, then its getting bad data. If you want to keep with the unicode, then change it to W at the end. That should work.
insanoflex512
I think its because its expecting the class name to be in ANSI, but when you have the project in unicode, then its getting bad data.

This could happen, and that would immediately produce compiler warnings, if not errors. @DanaFo: if you see in compiler output warnings about casting do different types, like WNDCLASSA to WNDCLASSW or other way around, then this is the error. Either:
1) disable unicode setting if you want to use functions without A suffix and use ASCII strings
2) use unicode setting and write unicode strings (L prefix for string literals)
3) use explicit A suffix and use ASCII strings
4) use explicit W suffix and use unicode strings (L prefix for string literals)

And enable compiler setting that treats warnings as errors. You should always have 0 warnings in compiler output.

Edited by Mārtiņš Možeiko on
Thanks again guys, totally worked and great tips.