What do question marks (???) in Visual Studio watch window signify? - visual-studio

I've run into an exception and looking at variables in the watch window, I'm seeing some question marks (???). Does this mean it's pointing to an invalid address?

It means that the debugger can't figure out its value.
For example, you see this quite a bit if your code involves HWNDs. If you look through the Windows header files, it's defined like this via a macro:
struct HWND__{int unused;}; typedef struct HWND__ *HWND;
So the type of HWND is really the type "pointer to an HWND__". However, the HWND values you get from functions like CreateWindow() aren't actually pointers to anything.
But the debugger will try to figure out the value of the unused member in the struct, but can't do it:
You will also see these kinds of errors when the watched variable has bad or missing type information.

Is this a C++ style project?
The debugger typically uses the "???" string when it is able to evaluate an expression but is unable to garner any type information for a specific part of the display. This typically occurs because of missing or incorrect PDB symbols.
There is likely a way for this to occur if the expression is accessing corrupted data (overriten virtual tables or RTTI). But I do not 100% know if that is true.

Usually it means the pointer or reference is pointing to inaccessible memory, and thus it cannot get the value to present. For example, if you have a pointer that's supposed to point to a Foo, the debugger will normally interpret the bits that the pointer points to as a Foo--whether the pointer is valid or not. But in some cases, a wild pointer might point to a location that's not even mapped in the process space. In that case, the debugger cannot get the bits.

Related

How to view the result of an expression in MSVS2013?

I remember seeing somewhere that you can specify which dll to get the address of symbols so that one can use that variable in the watch window. I can't for the life of me remember where I saw this. The best that I can come up with is Format Specifiers in C++.
The reason I want this is so that I can see the visibility status of a window and MSVS keeps saying that identifier "IsWindowVisible" is undefined.
I was trying to use something like the following in the watch window:
::IsWindowVisible(m_hWnd),user32.dll
Using:
this->IsWindowVisible()
results in Function CWnd::IsWindowVisible has no address, possibly due to compiler optimizations. which is why I'm trying to use the win32 call. Ideas?
http://msdn.microsoft.com/en-nz/library/y2t7ahxk.aspx
Haven't tried it, but it seems to me that IsWindowVisible(m_hWnd) should work, or maybe IsWindowVisible(this->m_hWnd).

Visual studio 2010: how to watch a memory hex location

I tried some suggestions found online but it does not work for me. Im using Visual Studio 2010. Basically I typed loc(kcs(1,4)) (thats my variable) and I obtained 157510036. Its hex is 9636994. So then I typed (INTEGER*)0x9636994 but on the watch window under the "value"column it says "undefined variable INTEGER". I trid lowercase integer or real and same answer. Any suggestion?
I typed (INTEGER*)0x9636994 but on the watch window under the "value"column it says "undefined variable INTEGER".
According to Restrictions on Native C++ Expressions:
Type Casting
If you cast to a type, the type must be known to the debugger. You must have another object of that type in your program. Types created using typedef statements are not supported.
Try using the underlying type. So, for example, if INTEGER is actually an int you would try to watch (int *)0x9636994.
This also assumes that the variable is fixed at 0x9636994 (basically that you're not trying to refer to something transient on the stack).

"__NSAutoreleaseFreedObject(): release of previously deallocated object" out of the blue

I'm not sure if this is an error or not. The code compiles fine (no warnings), but when I enter a method, a local's value (an NSMutableString) displays this content in the debugger:
__NSAutoreleaseFreedObject(): release of previously deallocated object
I'm not getting an exception, it looks like the contents of the string (which is not even allocated at that time) is that NSAutoReleaseFreedObject warning.
What's going on?
If you don't initialize a normal local variable to anything, its value is undefined — it could be anything. In practice, it will interpret the bit pattern that happens to lie on the stack where the variable is allocated as a value of the variable's type. In this case, the "anything" that the variable contains happens to be the address of that string.
it (likely) means that your app has executed different from usual, and exposed a bug in your ref counting of the object. this type of issue can also be related to improper multithreading.
executing your app to trigger the problem with zombies enabled should help you locate it.

How to view the variable values in release builds

I want to be able to see the variable values while debugging a release application.
I have set the compiler option as Z7 and given a /DEBUG and /PDB: linker option. Now I have a pdb for the application.
With this set up I am able to put a break point (Windbg) inside the code and it hits properly. But I am not able to see the variable values.
The Locals window only shows the pointer value but I cant see the contents of the same. For instance if I have a pointer to a structure that has an int inside it, it just shows the value of the pointer. If I expand the same by clicking + in the tree, I see the variable name with the value as <Memory access error>
How should I make the release builds show the variable values?
Many times, you cannot see them because they don't exist. If you look at the optimized assembly code, you will find that many intermediate variables are completely removed in favor of performance. That is most likely what you're seeing, and the only way around it is to follow the disassembly and watch the right memory locations / registers.

How to read a call stack?

We have a native C++ application running via COM+ on a windows 2003 server. I've recently noticed from the event viewer that its throwing exceptions, specifically the C0000005 exception, which, according to http://blogs.msdn.com/calvin_hsia/archive/2004/06/30/170344.aspx means that the process is trying to write to memory not within its address space, aka access violation.
The entry in event viewer provides a call stack:
LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0xa26c
LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0x8af4
LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0x13a1
LibFmwk!utilCLogController::GetFLFInfoLevel(void)const + 0x1070
LibFmwk!utilCLogController::GetFLFInfoLevel(void)const + 0x186
Now, I understand that its giving me method names to go look at but I get a feeling that the address at the end of each line (e.g. + 0xa26c) is trying to point me to a specific line or instruction within that method.
So my questions are:
Does anyone know how I might use this address or any other information in a call stack to determine which line within the code its falling over on?
Are there any resources out there that I could read to better understand call stacks,
Are there any freeware/opensource tools that could help in analysing a call stack, perhaps by attaching to a debug symbol file and/or binaries?
Edit:
As requested, here is the method that appears to be causing the problem:
BOOL UTIL_GetDateFromLogByDayDirectory(LPCSTR pszDir, utilCDate& oDate)
{
BOOL bRet = FALSE;
if ((pszDir[0] == '%') &&
::isdigit(pszDir[1]) && ::isdigit(pszDir[2]) &&
::isdigit(pszDir[3]) && ::isdigit(pszDir[4]) &&
::isdigit(pszDir[5]) && ::isdigit(pszDir[6]) &&
::isdigit(pszDir[7]) && ::isdigit(pszDir[8]) &&
!pszDir[9])
{
char acCopy[9];
::memcpy(acCopy, pszDir + 1, 8);
acCopy[8] = '\0';
int iDay = ::atoi(&acCopy[6]);
acCopy[6] = '\0';
int iMonth = ::atoi(&acCopy[4]);
acCopy[4] = '\0';
int iYear = ::atoi(&acCopy[0]);
oDate.Set(iDay, iMonth, iYear);
bRet = TRUE;
}
return (bRet);
}
This is code written over 10 years ago by a member of our company who has long since gone, so I don't presume to know exactly what this is doing but I do know its involved in the process of renaming a log directory from 'Today' to the specific date, e.g. %20090329. The array indexing, memcpy and address of operators do make it look rather suspicious.
Another problem we seem to have is that this only happens on the production system, we've never been able to reproduce it on our test systems or development systems here, which would allow us to attach a debugger.
Much appreciated!
Andy
Others have said this in-between the lines, but not explicitly. look at:
LibFmwk!UTIL_GetDateFromLogByDayDirectory(char const *,class utilCDate &) + 0xa26c
The 0xa26c offset is huge, way past the end of the function. the debugger obviously doesn't have the proper symbols for LibFmwk so instead it's relying on the DLL exports and showing the offset relative to the closest one it can find.
So, yeah, get proper symbols and then it should be a breeze. UTIL_GetDateFromLogByDayDirectory is not at fault here.
if you really need to map those addresses to your functions - you'll need to work with .MAP file and see where those addresses really point to.
But being in your situation I would rather investigate this problem under debugger (e.g. MSVS debugger or windbg); as alternative (if crash happens at customer's site) you can generate crash dump and study it locally - it can be done via Windows MiniDumpWriteDump API or SysInternals ProcDump utility (http://download.sysinternals.com/Files/procdump.zip).
Make sure that all required symbol files are generated and available (also setup microsoft symbol server path so that windows DLLs' entry points get resolved also).
IMHO this is just the web site you need: http://www.dumpanalysis.org - which is the best resource to cover all your questions.
Consider also taking a look at this PDF - http://windbg.info/download/doc/pdf/WinDbg_A_to_Z_color.pdf
Point 2 and 3 are easily answered:
3rd Point. Any debugger. That's what they are made for. Set your debugger to break on this special exception. You should be able to click yourself through the callstack and find the different calls on the stack (at least delphi can do this, so visual studio should be able as well). Compile without optimisations if possible. OllyDBG might work as well - perhaps in combination with its trace functionality.
2nd Point. Any information about x86 Assembler, Reverseengineering ... Try: OpenRCE, NASM Documentation, ASM Community.
1st Point. The callstack tells you the functions. I don't know if it is written in order or in opposite order - so it might be that the first line is the last called function or the first called function. Follow the calls with the help of the debugger. Sometimes you can change between asm and code (depending on the debugger, map files ...). If you don't have the source - learn assembler, read about reverse engineering. Read the documentation of the functions you call in third party components. Perhaps you do not satisfy a precondition.
If you can tell a bit more about the programm (which parts of the source code do you have, is a library call involved?, ...)
Now some code-reading:
The function accepts a pointer to a zero terminated string and a reference to a date object. The pointer is assumed to be valid!
The function checks wether the string is in a specific format (% followed by 8 digits followed by a \0). If this is not the case, it returns false. This check (the big if) accesses the pointer without any validity checks. The length is not checked and if the pointer is pointing somewhere in the wild, this space is accessed. I don't know if a shorter string will cause problems. It shouldn't because of the way && is evaluated.
Then some memory is allocated on the stack. The number-part of the string is copied into it (which is ok) and the buffer gets its \0 termination. The atois extract the numbers. This will work because of the different start-locations used and the \0-termination after each part. Somehow tricky but nice. Some comments would have made everything clear.
These numbers are then inserted into the object. It should be valid since it is passed into the function by reference. I don't know if you can pass a reference to a deleted object but if this is the case, this might be your problem as well.
Anyway - except the missing check for the string-pointer, this function is sound and not the cause of your problem. It's only the place that throws the exception. Search for arguments that are passed into this function. Are they always valid? Do some logging.
I hope I didn't do any major mistakes as I am a Delphi programmer. If I did - feel free to comment.

Resources