Общий способ решения ошибки: стек с переменной x был поврежден - программирование

Общий способ решения ошибки: стек с переменной x был поврежден

У меня есть программа, которая вызывает ошибку в VS2010, в отладке:

Error: Stack around the variable 'x' was corrupted

Это дает мне функцию, в которой происходит переполнение стека, но я не могу визуально увидеть, где проблема.

Есть ли общий способ отладки этой ошибки с VS2010? Можно ли указать, какая операция записи перезаписывает неправильную память стека? спасибо

4b9b3361

Ответ 1

Есть ли общий способ отладки этой ошибки с VS2010?

Нет, нет. То, что вы сделали, - это каким-то образом вызвать поведение undefined. Причина такого поведения undefined заключается в том, что общий случай очень трудно обнаружить/диагностировать. Иногда это невозможно сделать.

Однако есть несколько незначительное количество вещей, которые обычно вызывают вашу проблему:

  • Неправильное обращение с памятью:
    • Удаление чего-то дважды,
    • Использование неправильного типа удаления (free для чего-то выделенного с помощью new и т.д.),
    • Доступ к чему-то после его удаления.
  • Возврат указателя или ссылки на локальный.
  • Чтение или запись за конец массива.

Ответ 2

Это может быть вызвано несколькими проблемами, которые обычно трудно увидеть:

  • двойное удаление
  • delete переменная, выделенная с помощью new[] или delete[] переменной, выделенной с помощью new
  • delete что-то выделено malloc
  • delete переменная автоматического хранения
  • возвращает локальную ссылку

Если это не сразу станет ясно, я возьму руки на отладчик памяти (я могу думать о Rational Purify для Windows).

Ответ 3

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

Ответ 4

На самом деле то, что вы видите, достаточно информативно, вы должны проверить местоположение переменной x для любой активности, которая может вызвать эту ошибку.

Ниже вы можете воспроизвести такое исключение:

int main() {
    char buffer1[10];
    char buffer2[20];
    memset(buffer1, 0, sizeof(buffer1) + 1);
    return 0;
}

будет генерировать (VS2010):

Ошибка проверки времени выполнения # 2 - поврежден стек вокруг переменной "buffer1".

Очевидно, memset написал 1 char больше, чем нужно. VS с опцией \GS позволяет обнаруживать такие переполнения буфера (которые вы включили), более подробно об этом читайте здесь: http://msdn.microsoft.com/en-us/library/Aa290051.

Вы можете, например, использовать debuger и переходить через ваш код, каждый раз наблюдать за содержимым вашей переменной, как они меняются. Вы также можете испытать удачу с точками перехвата данных, вы установите точку останова, когда некоторые изменения местоположения памяти и отладчик прекратятся в этот момент, возможно, показывая вам столбец, где находится проблема. Но это может не работать с флагом GS.

Для обнаружения переполнения кучи вы можете использовать инструмент gflags.

Ответ 5

Я был озадачен этой ошибкой в ​​течение нескольких часов, я знаю возможные причины, и они уже упоминаются в предыдущих ответах, но я не выделяю память, не обращаюсь к элементам массива, не возвращаю указатели на локальные переменные...

Затем, наконец, нашел источник проблемы:

*x++;

Цель заключалась в том, чтобы увеличить указанное значение. Но из-за приоритета ++ на первом месте, перемещая указатель x вперед, а затем * ничего не делает, тогда запись в *x будет повреждена стека канарейкой, если параметр поступает из стека, заставляя VS жаловаться.

Изменение этого параметра на (*x)++ решает проблему.

Надеюсь, что это поможет.

Ответ 6

Вот что я делаю в этой ситуации:

Установите точку останова в месте, где вы можете увидеть (правильное) значение рассматриваемой переменной, но до возникновения ошибки. Вам понадобится адрес памяти переменной, чей стек поврежден. Иногда мне нужно добавить строку кода, чтобы отладчик легко передал мне адрес (int * x = & y)

В этот момент вы можете установить контрольную точку памяти (Debug- > New Breakpoint- > New Data Breakpoint)

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

Ответ 7

Я обычно следую за переменной перед переменной-жалобой, которая обычно помогает мне получить проблему. Но это может когда-нибудь быть очень сложным, без подсказки, как вы его видели. Вы можете включить Debug menu → Exceptions и пометить "Исключения Win32", чтобы поймать все исключения. Это все равно не поймает эти исключения, но может поймать что-то еще, что косвенно может указывать на проблему.

В моем случае это было вызвано библиотекой, которую я использовал. Это явка заголовочного файла, который я включил в мой проект, не совсем соответствовала фактическому заголовочному файлу в этой библиотеке (по одной строке).

Существует и другая ошибка:

0xC015000F: деактивированный контекст активации не самый недавно активированный.

Когда я устал от получения загадочного сообщения о поврежденном стеке на своем компьютере без отладочной информации, я попробовал свой проект на другом компьютере, и вместо этого он дал мне вышеуказанное сообщение. С новым исключением я смог выработать свой путь.

Ответ 8

Я столкнулся с этим, когда создал массив указателей из 13 элементов, а затем попытался установить 14-й элемент. Изменение массива на 14 элементов решило проблему. Надеюсь, это поможет некоторым людям ^ _ ^