Вопрос фундаментальный. Позволю себе "обсосать" свое понимание оного (рискуя вызвать гнев народа). Стек хаваеЦЦа (и куриЦЦа):
* при вызове функции
* при создании определенных юзером переменных с автоматическим классом памяти, видимых только в пределах этой функции
* для создания "автоматических автоматических" переменных, которые создает компилер по мере надобности.
Поскольку все эти переменные могут быть по разному упакованы в зависимости от опций комплера и его настроения, то по вычислить все это только по отвечтам компилера и линкера едва ли возможно.
Анализировать полный граф переходов по асмовому листингу компилера более перспективно, но вопрос в том, насколько вычисленный худший случай будет близок к реальности. Сложатся ли в реальной жизни все ветви переходов именно так, чтобы стэк отъехал по максимуму? Насчет реентерабельных рекурсивных модулей, которые data driven, вероятно, за их создание надо расстреливать.
Если у нас 1Г памяти на борту - ну и хрен с ним, поставим стеки по максимуму.
Если у нас несколько кБайт ОЗУ на борту - жалко!
Более перспективно было бы, если бы компилер имел такие возможности.
#pragma __STACK_CONTROL_ON__ - типа разрешаем заниматься нижеследующим.
В самом начале потока
#pragma __THREAD_START__
С этого момента заводятся четыре переменных потока, указатели на которые передаются всем функциям в потоке:
* *stack_base - указатель на начало стека потока
* thread_stack_max - при реальных операциях со стеком вычисляем, сколько схавали и thread_stack_max = MAX (thread_stack_current, thread_stack_max)
* bool thread_stack_oversize - типа флаг
* *PC - типа тут мы нашли, что вылезли за границу стека, чтобы в листинге ковыряться
Поскольку в дебугере мы можем в любой момент посмотреть все регистры, то там действительно можно родить скрипт, который все это будет ослеживать без включения "левого" кода. Вопрос только в том, не закончится ли свет во вселенной раньше, чем мы завершим дебуггинг.
Программынй метод приведет к трате некоторого количества ОЗУ и кода, но его можно присобачить к любой архитектуре.
Вот тут можно покурить несколько методов, основанных на анализе содержимого памяти
http://en.wikipedi …ck-smashing_protection
Там же даже до меня, наконец, дошло, что MMU в рамках нынешней дескрипторной парадигмы является бесполезной фичей для практических embedded целей. Ибо если заMMUшивать каждый вызов функции, то СoreDuo, вероятно, с трудом догонит 386SX-40 Мгц. А без заммушивания не толко кульхацкеры, но и наши баги будут приводить к чудесатым результатам, и нифига мы с этим не поделаем. ММУ же только лишь сообшит нам, что процессу - кабздец. Картинка по то ссылке хорошая, даже до меня, наконец, все дошло!
Собственно, мудры люди пару лет наза на электрониксе втолковывали в мою тупую бошку, что ММУ бесполезен. Только теперь я догнал:
* ММУ дастст нам знать, что процессу кабздец
* если другие процессы были зависимы от него, то им тоже хана. "Ракета упала в безлюдном районе".
* если другие процессы были независимы - то может, здохший процесс и ненужен вовсе???
Нет, ну когда-то где то MMU нас выручит. Для дебуггинга он вообще незаменим (токо вот я пока не знаю дебугеров, который имели бы скриптовый язык для программирования MMU. Многие JTAG дебугеры только сейчас узнали о существовании MMU, и сильно тащатся от этого
http://www.ronetix.at )! Но говорить о том, что MMU решит все проблемы - нельзя!!!
Для эффективной борьбы с такой хренотой идеальным был бы memory coprocessor, но обсуждать создание новой особоправильной процессорной архитектуры мы не будем.
Вопрос. А есть ли компилеры, который делают что-то похожее на описанною мною выше? Что насчет фич GCC в данной области?
P.S. Некоторое время назад, мне казалось, что я многое знаю о программировании embedded систем. Типа я крут! Но сейчас спираль зашла на второй круг - я стал задумываться о простых, ранее казавшихся мне самоочевидными вещах - и почувствовал, что вылетел в новое измерение. Я читаю все книги по C, C++ и пр уже по которому разу, и нахожу в них столько нового, что я просто охреневаю - как же я раньше его не видел??????????? Оно же кричит большими черными буквами со страниц этих книг!!!
В очередной раз убеждаюсь, что реальное инженерное дело - это помесь науки, искусства и эзотерики. Между этими составными частями нет внутреннего спора - они живут все вместе, ортогонально, не мешая друг другу. Задача толкового инженера лишь уловить весовые коэффициенты каждой из сущностей в контексте решаемой задачи в каждый конкретный момент времени.
Есдва ли все, даже ответственные софты, анализирут по стеку на 100%. Это невозможно (в классической С парадигме программирования точно! Я начинаю понимать, о чем думали разработчики ADA, о чем пишет Н. Вирт в своих книгах...). Но как-то же они работают...
Может, есть все-таки простой способ разобраться со всем этим?