Отладка стека отладки

Теперь я отлаживаю большой проект, который имеет повреждение стека: приложение терпит неудачу.

Я хотел бы знать, как найти (отладить) такой код коррупции стека с Visual Studio 2010?

Вот пример некоторого кода, который вызывает проблемы с стеком, как бы я нашел менее очевидные случаи такого рода коррупции?

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

Update

Обратите внимание, что это всего лишь пример. Мне нужно найти такой плохой код в текущем проекте.

Ответ 1

Существует один метод, который может быть очень эффективным с такими ошибками, но он будет работать только с подмножеством из них, который имеет несколько характеристик:

  • значение искажения должно быть устойчивым (т.е. как в вашем примере, когда происходит повреждение, всегда 100) или, по крайней мере, что-то, что можно легко идентифицировать простым выражением
  • коррупция должна происходить по определенному адресу в стеке
  • значение развращения довольно необычно, что вы не будете поражены множеством ложных срабатываний

Обратите внимание, что второе условие может показаться маловероятным на первый взгляд, потому что стек может использоваться многими различными способами в зависимости от действий во время выполнения. Однако использование стека обычно довольно детерминировано. Проблема в том, что конкретное местоположение стека может использоваться для множества разных вещей, в которых проблема действительно является элементом № 3.

В любом случае, если ваша ошибка имеет эти характеристики, вы должны определить адрес стека (или один из них), который поврежден, а затем установить точку останова памяти для записи на этот адрес с условием, которое заставляет его ломаться, только если значение, написанное, является повреждающим значением. В Visual Studio вы можете сделать это, создав "New Data Breakpoint..." в окне Breakpoints, затем щелкнув правой кнопкой мыши точку останова, чтобы установить условие.

Если вы получаете слишком много ложных срабатываний, это может помочь ограничить область точки останова, оставив ее отключенной до некоторой части пути выполнения, которая ближе к ошибке (если вы можете определить такое время), или установите максимальное количество хитов, чтобы удалить большую часть ложных срабатываний.

Дополнительным осложнением является адрес стека, который может меняться от запуска до запуска - в этом случае вам нужно будет позаботиться о том, чтобы установить точку останова при каждом прогоне (младшие биты адреса должны быть одинаковыми).

Ответ 2

Я считаю, что ваши вопросы цитируют пример коррупции стека, и вопрос, который вы задаете, не является причиной его сбоя.

Если это так, он выходит из строя, потому что он создает Undefined Поведение, потому что индекс -2 указывает на неизвестную ячейку памяти.

Чтобы ответить на вопрос о профилировании вашего приложения:
Вы можете использовать Rational Purify Plus для Visual Studio, чтобы проверить наличие ошибок и ошибок доступа.

Ответ 3

Это UB: p[-2] = 100;

Вы можете получить доступ к p с помощью operator[] в этом (p[i]) пути, но в этом случае i является недопустимым значением. Поэтому p[-2] указывает на недопустимое расположение памяти и вызывает Undefined Поведение.

Чтобы найти его, вы должны отлаживать свое приложение и находить, где он падает, и, надеюсь, он будет в месте, где что-то действительно не так.