Переполнение стека в вызове функции C - MS Visual C ++ 2010 Express - PullRequest
4 голосов
/ 03 февраля 2012

Я написал функцию на C, которая при вызове немедленно приводит к переполнению стека.

Прототип: void dumpOutput( Settings *, char **, FILE * );

Вызывающая линия: dumpOutput( stSettings, sInput, fpOut );

На момент вызова stSettings уже является указателем на структуру Settings, sInput является динамически размещаемым двумерным массивом, а fpOut является FILE *.Он доходит до вызывающей линии без каких-либо ошибок, утечек памяти и т. Д.

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

Я пытался вызывать ту же функцию напрямую из main() с фиктивными переменными для проверки, есть ли какие-либо проблемы с переданными аргументами, но все равно выбрасывает условие переполнения стека.

Ошибка возникает из chkstk.asm при вызове функции.Этот asm-файл (согласно присутствующим в нем комментариям) пытается проверить стек, чтобы проверить / выделить память для вызываемой функции.Он просто продолжает переходить к части Find next lower page and probe до тех пор, пока не произойдет переполнение стека.

Локальные переменные в dumpOutput также не являются зверями памяти, только 6 целых и 2 указателя.

Используемая памятькод в точке входа в эту функцию равен 60 936 КБ, которая увеличивается до 61 940 КБ в момент, когда происходит переполнение стека.Большая часть этой памяти уходит в sInput.Это причина ошибки?Я так не думаю, потому что передается только его указатель.Во-вторых, я не понимаю, почему dumpOutput пытается выделить 1004 КБ памяти в стеке?

Я в полном недоумении.Любая помощь будет высоко оценена.

Заранее спасибо.

Ответы [ 2 ]

4 голосов
/ 03 февраля 2012

В принципе, _chkstk () job создает исключение переполнения стека.Вы можете диагностировать это, посмотрев на сгенерированный машинный код.После того, как вы войдете в функцию, щелкните правой кнопкой мыши окно редактирования и выберите «Перейти к разборке».Вы должны увидеть что-то похожее на это:

003013B0  push        ebp  
003013B1  mov         ebp,esp 
003013B3  mov         eax,1000D4h                  ; <== here
003013B8  call        @ILT+70(__chkstk) (30104Bh) 

Значение, переданное через регистр EAX, является важным, это количество стекового пространства, необходимое вашей функции.Затем Chkstk проверяет, действительно ли он доступен, проверяя страницы стека.Если вы видите, что он многократно повторяется, тогда значение EAX в вашем коде высокое.Как и мой, он гарантированно потребляет все байты стека.И больше.От чего он защищает, обычно вы получаете исключение нарушения прав доступа.Но нет никакой гарантии, ваш код может случайно записать на отображенную страницу, которая принадлежит, скажем, куче.Что привело бы к невероятно трудной диагностике ошибки.Chkstk () помогает вам найти эти ошибки, прежде чем вы расстроите свой мозгисключение говорит, что у вас либо большой массив в качестве локальной переменной, либо вы передаете большое значение _alloca ().Исправьте, выделив этот массив из кучи.

0 голосов
/ 03 февраля 2012

Скорее всего, повреждение стека или ошибка рекурсии, но трудно ответить, не увидев никакого кода

...