Debug stack corruption

Sergey Vyacheslavovich Brunov picture Sergey Vyacheslavovich Brunov · Sep 3, 2011 · Viewed 11.7k times · Source

Now I am debugging a large project, which has a stack corruption: the application fails.

I would like to know how to find (debug) such stack corruption code with Visual Studio 2010?

Here's an example of some code which causes stack problems, how would I find less obvious cases of this type of corruption?

void foo()
{
    int i = 10;
    int *p = &i;
    p[-2] = 100;
}

Update

Please note that this is just an example. I need to find such bad code in the current project.

Answer

Michael Burr picture Michael Burr · Sep 3, 2011

There's one technique that can be very effective with these kinds of bugs, but it'll only work on a subset of them that has a few characteristics:

  • the corrupting value must be stable (ie., as in your example, when the corruption occurs, it's always 100), or at least something that can be readily identified in a simple expression
  • the corruption has to occur at a particular address on the stack
  • the corrupting value is unusual enough that you won't be hit with a slew of false positives

Note that the second condition may seem unlikely at first glance because the stack can be used in so many different ways depending on the runtime actions. However, stack usage is generally pretty deterministic. The problem is that a particular stack location can be used for so many different things that the problem is really item #3.

Anyway, if your bug has these characteristics, you should identify the stack address (or one of them) that gets corrupted, then set a memory breakpoint for a write to that address with a condition that causes it to break only if the value written is the corrupting value. In visual Studio, you can do this by creating a "New Data Breakpoint..." in the Breakpoints window then right clicking the breakpoint to set the condition.

If you end up getting too many false positives, it might help to narrow the scope of the breakpoint by leaving it disabled until some point in the execution path that's closer to the bug (if you can identify such a time), or set the hit count high enough to remove most of the false positives.

An additional complication is the address of the stack may change from run to run - in this case, you'll have to take care to set the breakpoint on each run (the lower bits of the address should be the same).