Click here to Skip to main content
15,884,739 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a global that has a pointer member in it. A program function calls into the global and initializes that pointer. Then later the pointer is accessed. For some reason in Debug mode, the pointer reads 'NULL' instead of the address of the newed pointer.

Using Visual Studio's Immediate window, the address of the pointer is the same at both places, so I don't appear to have a variable name conflict. The pointer is in a library that is a project of the solution, and is declared global there and 'extern'al in the main application. When stepping through, Visual Studio's mouse hover watch shows the pointer member holding a number (memory location), but when assigning it to a local variable, that local variable becomes NULL.

Oddly, the program seems to work in Release mode. The fact that the Debug version is flakey is concerning.

Does anyone have any ideas to help debug this further?

Thanks!

What I have tried:

I've tried moving the initialization of the member to the line right before the access:
C++
gDwlGlobals->setupItemsNeedingHwnd(); //Initialize 'dialogs'
void * address = &gDwlGlobals->dialogs; //For debugging, to see address
dwl::WinDialogs * d = gDwlGlobals->dialogs; //Here it is NULL, even though I just
                                            //stepped through and watched it initialize
d = gDialogs; //If, when I initialize it in 'setupItems...', I create another global
              //pointer and assign the memory address to it, and use that instead
              //of the main gDwlGlobal->dialogs, it will show up correctly here!

It didn't work, although the second assignment to a secondary global did work.

Another clue is that the 'hover' action in the debugger where I take the pointer's address as a void * shows the address being 20 bytes off from the value given by the Immediate window. What would cause that?
Posted
Updated 27-Mar-18 21:39pm

1 solution

This can't be answered without knowing the type of the gDwlGlobals variable, how it is initialised, and what setupItemsNeedingHwnd() is doing (what is assigned to the dialogs member).

But
void * address = &gDwlGlobals->dialogs;
gets the address of the dialogs member (the address of gDwlGlobals plus an offest) while
dwl::WinDialogs * d = gDwlGlobals->dialogs;
gets the value of the dialogs member (which is also a pointer).

These values will never be the same. It explains also why you have an offset of 20 bytes between address and gDwlGlobals shown by the immediate window.

One difference between debug and release builds is that variables are initialised with zero / NULL in debug builds while they contain random values in release builds. This applies not to global (static) variables which are always initialised with zero / NULL. But your gDwlGlobals is a pointer so that only the pointer is initialised with NULL.

Ensure also that your program has executed until a specific point before checking variables in the Immediate window. If you set for example a breakpoint on the setupItemsNeedingHwnd() line, that will not be executed. To see the effects of that function you have to set the breakpoint on the next line.
 
Share this answer
 
Comments
David O'Neil 28-Mar-18 10:46am    
Thanks for the response, Jochen. I got some sleep, then simply put logging calls in at each step. And after they were installed it started working the way I thought it should. So I played around some more with the logging.

Eventually, it hit me. The library project had DWL_DO_LOGGING defined, and the main application didn't. So the extra 'logger' in the library global was throwing off the address! Duh!!! Back to my universal header!

Have a '5' for your time! Thanks!
Jochen Arndt 28-Mar-18 11:54am    
Thank you for your feedback and fine to hear that all is solved.
Rick York 28-Mar-18 13:24pm    
The moral of the story is avoid adding data members based on macro definitions especially when those definitions are outside of the data declaration. I have been bitten by this only a few times but the last one cost about two days and I have never done it again. In that case, I was using a library built in release mode with an app built in debug mode. The FILE structure had an extra member in debug mode and when I passed a FILE pointer into the library it would crash. This was a fairly obscure case but I have avoided doing anything like that since then. This was not something in code actually, but the situation was definitely a learning experience on several topics.
David O'Neil 28-Mar-18 14:02pm    
Yeah, it cost me a day. Lesson learned? I've added another configuration to the solution that has 'Debug' and 'Do Logging' enabled. Had a bit of frustration because when I added it, both the Debug and Release configurations switched to 64 bit! And couldn't quickly see how to fix it - thought I was going to have to recreate the entire solution! But figured it out.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900