Advertisement

Warning to all Win32 programmers!!!

Started by August 23, 2000 04:00 PM
12 comments, last by baskuenen 24 years, 4 months ago
I just want to warn you for "a special kind of bug": This is some of the faulty source code:
        
//------------------------------------------------------------------------------

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ 
	switch (uMsg) 
	{	case WM_COMMAND:
			switch(LOWORD(wParam))
			{	case ID_MAP_GENERATE:
				{	//

					//  Here comes the error:

					//

					int Map[256*256];	// Error ? - !

					//  do some other stuff here...

					return 0;
				}
			}
			break;
	}
}
        
My program ran fine, until I wanted to MOVE my window. I checked everything that could be wrong but I just couldn't find it Now it's obvious, but it wasn't at the time. That map I created, uses a lot of memory. After you move a window, windows probably calls the WndProc multiple times. Every time this WndProc is called the DefWindowProc does some sort of recursive call, and this way the stack gets a big hit. The stack gets an overflow an exception is created, and your program hangs with a stupid stack error message. To avoid it, it's probably best to use calls to functions in the WndProc, and not to do stuff IN the WndProc. Let that function alloc the stack, not the WndProc!!! Just thought I'd mention it, and spare you lots of frustration... Edited by - baskuenen on 8/23/00 4:12:49 PM
Why on EARTH are you defining a variable inside a conditional structure ???

I am even wondering how the hck the compiler accepted this code.

youpla :-P
-----------------------------Sancte Isidore ora pro nobis !
Advertisement
It's the ++ that does the trick It can provide better to read code. The compiler will probably generate the same code...

If I would define it at the start of the function, the error would still occur!



Edited by - baskuenen on August 23, 2000 5:41:35 PM
ahw: the variable is declared within a block {...} so in the eyes of the compiler this is perfectly legal. It should however complain about the following:

    switch (ANYTHING){    case SOMETHING:        int map[256];        break;    case SOMETHING_ELSE:        break;};    


because the declaration may be "missed" by other case labels.
but as long as you put a block around the declaration its scope is only within that block and it is therefore legal.
You are correct about the stack hit. Even though you can create local variables at any point in a function in C++, the memory for all of these variables is allocated for each call, just as it is in C. The only thing you gain by creating local variables at the last minute is you don't have to call all the constructors if different variables are in different blocks. This can be a huge gain, but not in your case (int doesn't have a constructor).

Regardless of some might think of your design, it's legal and won't cause any compiler errors or warnings. However, that much memory should really be allocated on the heap, not the stack. Moving it into a function will still cause a stack hit, only not for every WinProc call. Just change the variable from "int map[256*256]" to "int* map = new int (256*256)", and remember to delete it later.

As a rule of thumb, the most I ever allocate to a single stack variable is 4096 bytes (MAX_LEN for some win32 stuff). This is the same as 1024 ints. Anything more really should go in the heap.

Edited by - Stoffel on August 23, 2000 6:06:55 PM
Something i have never really been sure about...what is the difference in stack memory and heap memory? As i am starting to program more and more and doing more complex programs a lot of this stuff is starting to mean something to me and have relevance.

Does the new operator automatically allocate heap memory?
Advertisement
just someit else going int map[3] = {2,2,2}; is illegal
(im talking about in the above case statement)

Edited by - zedzeek on August 23, 2000 6:21:54 PM
Yes, I know.

I think Windows gives you 1MB of stack space as a standard.
If you would pull that 256K tricks once at a time, you'd probably never get into trouble unless you have a OS that begins calling your functions recursively...

Plus:
- using the stack is faster.
- using the stack can prevent memory leaks (simple use of try/catch for example)

But you're right Stoffel, it would provide more secure code if you're use the heap more often



Edited by - baskuenen on August 23, 2000 6:56:03 PM
quote:
Yes, I know.

I wasn''t so much speaking for you as I was for the other people who are reading this thread and (judging from the responses) not understanding the issue.

quote:
Plus:
- using the stack is faster.
- using the stack can prevent memory leaks (simple use of try/catch for example)

yeah, on the first point there''s no question. However, there are a plethora of ways to deal with the second point, the best being a wrapper class. I''m no big fan of auto_ptr, simply because I''ve never used it and it gives me a creepy feeling, but I understand it works great. Also, I''m guessing you can use:
vector&ltint> map (256*256)
and get almost the same functionality you have AND gives you a stack-local variable that uses the heap for its contents.

quote:
(int doesn''t have a constructor).


Just a note ..

I thought I read somewhere that all the intrinsic types for C++ (at least under Visual C++) where actually classes.

The following code is valid:

        int i(5);    int *pi = new int(7);    


This topic is closed to new replies.

Advertisement