Любой способ заставить локальные переменные в стек в 64-битном приложении VC - PullRequest
6 голосов
/ 10 февраля 2010

Когда 64-битное приложение VC 2005 скомпилировано с включенной оптимизацией, невозможно увидеть все локальные переменные в файле аварийного дампа. Во многих случаях локальные переменные или параметры хранятся в регистрах, а не в стеке. Последующие вызовы других функций, таких как функции обработки ошибок, иногда перезаписывают эти значения. Это затрудняет отслеживание причины проблемы. Есть ли способ заставить локальные переменные и / или параметры в стеке во время выполнения?

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

- Alex

Ответы [ 4 ]

3 голосов
/ 11 февраля 2010

Я думаю, вы видите что-то еще. Наиболее распространенные соглашения о вызовах в x86 передают аргументы аргументам функции в стеке. Но соглашение о вызовах x64 отличается, оно похоже на __fastcall на x86, оно передает первые 4 аргумента функции в регистрах (rcx, rdx, r8 и r9). Если функция нетривиальна, компилятор генерирует код для немедленного сохранения этих регистров в кадре стека.

К сожалению, отладчик недостаточно умен, чтобы знать о сохраненных местоположениях регистров. Он отображает значение регистра в стеке вызовов, значение, которое почти всегда менялось. Вы можете технически извлечь значение аргумента из стекового фрейма самостоятельно, но вы действительно, действительно хотите это сделать. В оптимизированном коде это смещение от rsp, а не rbp, и значение указателя стека также изменилось.

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

1 голос
/ 04 марта 2015

Если вы обновитесь до VC ++ 2013 и используете ключ / Zo, тогда вы получите гораздо лучший опыт отладки с оптимизированным кодом, будь то 32-битный или 64-битный. Это не отвечает на ваш буквальный вопрос о том, как перевести переменные в стек, но он отвечает на ваш актуальный вопрос о том, как упростить просмотр значений локальных переменных и параметров.

1 голос
/ 10 февраля 2010

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

#ifdef DEBUG
 #define FORCE_ON_STACK(var)  void * p##var##_dummy = (void *)&var
#else
 #define FORCE_ON_STACK(var)  (void)0 // eat the ;
#endif

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

0 голосов
/ 11 февраля 2010

Есть ли способ принудительно помещать локальные переменные и / или параметры в стек во время выполнения?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...