2008-09-24 2 views
29

Есть ли способ узнать и вывести размер стека, необходимый функции во время компиляции в C? Вот что я хотел бы знать:Проверка использования стека во время компиляции

Давайте возьмем некоторую функцию:

void foo(int a) { 
    char c[5]; 
    char * s; 
    //do something 
    return; 
} 

При составлении этой функции, я хотел бы знать, сколько места в стеке будет потреблять whent это называется. Это может быть полезно для обнаружения декларации на стеке структуры, скрывающей большой буфер.

Я ищу что-то, что бы напечатать что-то вроде этого:

файла foo.c: функция использования стека Foo является n байтами

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

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

Давайте по-другому: возможно ли узнать размер всех объектов, локальных для функции? Я думаю, что оптимизация компилятора не будет моим другом, потому что какая-то переменная исчезнет, ​​но верхний предел будет прекрасен.

+0

В случае, если вам было интересно, я набрал секретный символ «}» – 2008-09-24 08:33:08

+0

Вопрос мне кажется непонятным. Я думаю, если вы напишете больше о том, почему вы хотите это знать, и почему проверка дизассемблирования или исполняемого файла (который является самым простым способом проверки вывода компилятора) неприемлема, возможно, кто-то может найти какое-то простое решение? – Suma 2008-09-24 11:28:11

ответ

10

Код ядра Linux работает на стеке 4K на x86. Поэтому им все равно. То, что они используют, чтобы проверить это, является написанным perl-скриптом, который вы можете найти как скрипты/checkstack.pl в недавнем архиве tar (у него есть 2.6.25). Он запускается на выходе objdump, документация по использованию находится в исходном комментарии.

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

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

Btw, с objdump из проекта mingw и ActivePerl, или с Cygwin, вы должны иметь возможность делать это также в Windows, а также в бинарниках, полученных с другими компиляторами.

1

Только компилятор действительно знал бы, так как это парень, который объединяет все ваши вещи. Вам нужно будет взглянуть на сгенерированную сборку и посмотреть, сколько места зарезервировано в преамбуле, но на самом деле она не учитывает такие вещи, как alloca, которые выполняют свою задачу во время выполнения.

+0

теоретически статические анализаторы кода, такие инструменты, как lint, могут выполнять свою работу, практически я не думаю, что они это делают. – Ilya 2008-09-24 08:49:48

-1

В целом. Проблема остановки в теоретической информатике предполагает, что вы даже не можете предсказать, останавливается ли общая программа на заданном входе. Вычисление стека, используемого для запуска программы в целом, было бы еще более сложным. Итак: нет. Может быть, в особых случаях.

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

+0

Ваш разговор о стеке процессов, а не о том, как будет использоваться каждый вызов функции – shodanex 2008-09-24 10:18:33

+0

Проблема с остановкой не останавливает статический анализ (т. Е. В компиляторах) и дает приблизительные ответы, просматривая текст программы. На самом деле большой проблемой является вычисление, когда две разные программы эквивалентны, поэтому две эквивалентные программы могут давать разные результаты при статическом анализе. – Blaisorblade 2009-01-12 08:46:19

3

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

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

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

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

Если вы хотите 100% точную цифру, то вы должны смотреть на выходе из компилятора или проверить его во время выполнения (например, Ральф предложил в his reply)

+1

StackAnalyzer кажется приятным, но он не выполняет задание, так как он анализирует исполняемый файл, а не исходный код. При написании такого инструмента действительно должно быть возможно в теории, я не уверен, что существует такой инструмент - проверка времени выполнения стека или на основе сборки - это очень практично. – Suma 2008-09-24 11:25:25

8

StackAnlyser кажется, examinate сам исполняемый код плюс некоторые сведения об отладке. Что такое this reply, это то, что я ищу, анализатор стека выглядит как излишний.

Нечто похожее на то, что существует для ADA, будет в порядке. Посмотрите на данной странице руководства от комара руководства:

22,2 Статических стек Анализ использования

Блока собран с -fstack-использованием будет генерировать дополнительный файл, который определяет максимальное количество стеки, используемое на функции каждого основа. Файл имеет такое же базовое имя, что и файл целевого объекта с расширением .su. Каждая строка этого файла состоит из трех полей:

* The name of the function. 
* A number of bytes. 
* One or more qualifiers: static, dynamic, bounded. 

Второе поле соответствует размеру известной части функции кадра.

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

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

1

Предполагая, что вы находитесь на встроенной платформе, вы можете обнаружить, что ваша инструментальная цепочка имеет дело с этим. Хорошие коммерческие встроенные компиляторы (например, компилятор Arm/Keil) часто создают отчеты об использовании стека.

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

1

Не совсем «времени компиляции», но я хотел бы сделать это как шаг после сборки:

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

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

Для реализации этого вам необходимо:

  • быть в состоянии разобрать файл карты
  • понимают формат исполняемого файла
  • знать, что функция пролог может выглядеть и быть в состоянии «расшифровывает» его

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

Все это можно сделать в x86/Win32, но если вы никогда не делали ничего подобного и должны были создать все это с нуля, это может занять несколько дней, прежде чем вы закончите, и у вас есть что-то работающее ,

Смежные вопросы