setjmp и пропустить указатель кадра - PullRequest
5 голосов
/ 04 мая 2011

Я пытался отследить случайную ошибку в моем коде (которая использует setjmp) и сузил ее до: появляется при компиляции с / O2, уходит с / O2 / Oy-, т.е. только показываетup с отсутствующим указателем кадра.

http://msdn.microsoft.com/en-us/library/2kxx5t2c(v=vs.80).aspx предполагает, что setjmp требует указателя кадра.Таким образом:

  1. Кажется, что когда программа, использующая setjmp, скомпилирована с / O2, Visual C ++ автоматически генерирует код, который вызывает прерывистое повреждение стека.Это правда, или я что-то упустил?

  2. Мне кажется, что только функция, которая вызывает setjmp, должна быть скомпилирована с указателем кадра, остальная часть программы - дажефункции, которые вызывают longjmp - должны быть в порядке, чтобы пропустить указатель кадра.Это правда?

Редактировать: Я сузил это немного дальше.

Включение указателя кадра на функцию, которая вызывала setjmpничего не изменило, но это потому, что компилятор уже делал это, как и положено, явно замечая, что это нужно сделать, и делая это автоматически.

Разница была в том, что включил указатель кадра на main.Это не так странно, как кажется, так как сбой проявлялся взамен основного.Теперь, когда я думаю об этом, все примеры, которые я могу найти в быстром поиске Google использования setjmp, делают это в основном.Возможно, так получилось, что команда компиляторов Microsoft проверила его только таким образом.

Поскольку это идиоматический способ его использования, возможно, лучшим обходным решением для меня было бы просто встроить функцию setjmp-using в main.

Ответы [ 3 ]

3 голосов
/ 12 мая 2011

Хорошо, я опубликовал отчет об ошибке с отдельным тестовым примером, так что, надеюсь, исправление находится в стадии разработки: http://connect.microsoft.com/VisualStudio/feedback/details/666704/visual-c-generates-incorrect-code-with-omit-frame-pointer-and-setjmp

Тем временем, обходной путь: либо не использовать указатель пропускаемого кадра, либо поместить код, вызывающий setjmp, в main, либо поместить функцию, вызывающую longjmp, в тот же исходный файл, что и вызов setjmp.

0 голосов
/ 05 ноября 2011

setjmp реализован множеством разных способов, но это, вероятно, как-то связано с реализацией сборки для вашей конкретной ОС.

Когда функция компилируется с использованием __stdcall, аргументы сохраняются относительно указателя кадра. Ваша реализация может получать доступ к аргументам setjmp относительно указанного указателя, поэтому ей не нужно выбрасывать несколько регистров, сохраняя для них контекст (так как это разрушит большую часть смысла setjmp); Кажется, я помню, что setjmp реализован таким образом в ядре Linux.

Конечно, если msvc не генерирует инструкции для установки ebp, то это не сработает и обязательно вызовет сбой.

0 голосов
/ 12 мая 2011

Можете ли вы указать более подробную информацию о самой аварии? Я имею в виду, какой код, сгенерированный компилятором для longjmp, происходит ли сбой сразу после longjmp, или когда вы пытаетесь получить доступ к автоматическим переменным, или когда вы пытаетесь выйти из функции?

Полагаю, что функция target должна быть скомпилирована со стандартным стековым фреймом, кажется, нет разумных ограничений для функции, которая использует longjmp.

...