|
|||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||
|
Announcements
Services
Chapters
Feature Zones
|
IntroductionLet's start with the reason why I wrote this article. One day, a colleague asked me to help him debug a problem he had. So I was watching him stepping in his code, when I noticed the following line: int test = GetLastError();
He did this, because he wanted to know the error code, if the previous function failed. He was adding this line every time he wanted to know the error code. I advised him to remove all those lines and use the @ERR pseudoregister in his watch window. He didn't know what it was and asking around in the office, a lot of other people didn't. So I came up with this article for people who have never heard of pseudoregisters. What is a pseudoregister anyway?A pseudoregister is not an actual hardware register, but is displayed as though it were a hardware register. With a pseudoregister, you can see and use certain values (error codes, thread information block...) in the debugger. Let's have a look at the @ERR pseudoregister. Fire up your debugger with your
favourite home-written application. Put a breakpoint in your code so that the
debugger will break execution. Open the watch window if it isn't already (do
this by right clicking on some empty toolbar space, and select "Watch" from this
list). Add @ERR in this watch window. You should see 0 in the Value column. Now
step through your code, and watch this value. It will always show the
If you want to test this, but your code doesn't have any errors, I advise to put some in (but don't forget to remove them afterwards). You can insert something like this: FILE *fp = fopen("c:\\a_file_that_does_not_exist.txt", "r"); If you step over this line, you'll see that the @ERR value changed to 2. Go to Tools->Error Lookup to see what this error value means ("The system cannot find the file specified" if you were wondering). Lazy bums like me, and smart lads / lasses like you can change the @ERR pseudoregister to @ERR,hr . Doing this will change the value of the pseudoregister to the error string. Now you even don't have to lookup the error. I leave the @ERR,hr in the watch window all the time. Conditional ExpressionsPseudoregisters can also
be used in conditional expressions. To try this out, put following lines after
the if (fp)
{
fclose(fp);
}
Put a breakpoint on the Just for the very curious (and
otherwise totally irrelevant to this article) : what does @ERR do? How does it
get the error number? As it turns out, @ERR does exactly the same thing as
mov eax,fs:[00000018h]
mov eax,dword ptr [eax+34h]
ret
So The @TIB pseudoregister The @ERR pseudoregister is not the only one that exists. Another important pseudoregister
is @TIB. This is the thread information block for the current thread and is
extremely helpful in multi-threaded debugging. If you place a breakpoint in a
function that is called by multiple threads, the debugger will break execution
every time no matter which thread passes the breakpoint. Even if you're stepping
through your code, the debugger can jump to the breakpoint if another thread
called the function. To solve this, you'll need to do the following. If
execution breaks in the thread you want, add @TIB in the watch window. You will
see some value like "0x7ffa6000" or "2147115008" in regular display. Go to the
breakpoint menu (Alt-F9) and select the breakpoint. You can now add the
This doesn't work in Windows 98 though. For Windows 98,
you'll need to look at the Intel CPU FS register, which is unique for each
thread. You can use the expression Complete list of pseudoregisters
[Table from "Debugging Applications" by John Robbins] AcknowledgementsJohn Robbins for his "Debugging Applications" book
|
||||||||||||||||||||||||||||||||||||