Debugger commands (.step_filter) that make my life easier
This is a pretty cool and somewhat obscure debugger command. It allows you to tell the debugger what functions to skip if you are using the trace command ('t'). I think of the trace command as the 'step into' command though, but that is just me. Let's say we have the following simple application:
#include <stdio.h>
struct Foo {
Foo() : m_value(0) { }
int Increment() { return ++m_value; }
static void Print(int i) { printf("%d\n", i); }
int m_value;
};
int _cdecl main(int argc, char *argv[])
{
Foo f;
Foo::Print(f.Increment());
return 0;
}
If I were to run the program under the debugger and use the 't' command for each line, it would step into every function. I typically use 't' instead of 'p' because I usually want to step into a function at some point in time and I tend to press 'p' one too many times ;). Here is an example of the debugger session:
0:000> g test!main
> 13: {
0:000> t
> 14: Foo f;
0:000> t
> 4: Foo() : m_value(0) { }
0:000> t
> 15: Foo::Print(f.Increment());
0:000> t
> 6: int Increment() { return ++m_value; } [1]
0:000> t
> 15: Foo::Print(f.Increment());
0:000> t
> 7: static void Print(int i) { printf("%d\n", i); } [2]
0:000> gu
> 16: return 0;
0:000> t
> 17: }
0:000> t
test!__mainCRTStartup+0x102:
Let's look at the statement Foo::Print(f.Increment()); When using the trace command, it will first step into Foo::Increment ([1]) before stepping into Foo::Print() ([2]). But let's say that I never want to step into Foo::Increment because I know that it is a simple function that I do not want to debug. I can tell the debugger to ignore trace commands into this function with the .step_filter command. The command takes a semi-colon delineated list of fully qualified symbol names (which can include wildcards so you can filter out entire modules) to ignore. Let's see the debugger session again with this command:
0:000> g test!main
> 13: {
0:000> .step_filter "test!Foo::Increment"
Filter out code symbols matching:
test!Foo::Increment
0:000> t
> 14: Foo f;
0:000> t
> 4: Foo() : m_value(0) { }
0:000> t
> 15: Foo::Print(f.Increment());
0:000> t
> 7: static void Print(int i) { printf("%d\n", i); }
0:000> gu
> 16: return 0;
0:000> t
> 17: }
0:000> t
test!__mainCRTStartup+0x102:
You will see now that when I trace into Foo::Print(f.Increment()); that the f.Increment() call is executed but not trace into (ignored is not the right word because it has run, I just didn't see it line by line) and I step directly into Foo::Print(). I think this is a pretty powerful debugger command, it can save you a lot of time if you are always accidentally stepping into the wrong function like I always do ;).