Share via


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 ;).