Стек процесса

источник = http://otvety.google.ru/otvety/thread?ti...

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

Эта часть памяти называется стеком, так как она организована по принципу стека - последний записанный в него элемент будет забыт первым.
На русский язык слово "стек" можно перевести как "стопка". Для "визуализации" понятия "стек" можно представить себе стопку тяжелых, неподъемных книг. Читать корешки у книг можно в любом порядке, но новую книгу можно положить только сверху, и взять книгу из стопки можно так же только верхнюю.

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

Фрейм стека - это блок данных, описывающих информацию о ходе работы одной подпрограммы, выполняющейся в данный момент. В него входят:

  • 1. параметры подпрограммы
  • 2. адрес возврата из подпрограммы
  • 3. сохраненные регистры процессора на момент вызова подпрограммы (такое замечание: один из сохраненных регистров на архитектуре x86 - это ebp, который, по соглашению, используется в качестве указателя на текущий фрейм стека с небольшим смещением. Иными словами, в фрейме вызванной подпрограммы записывается адрес фрейма вызывающей подпрограммы, благодаря этому многие отладчики могут восстановить всю цепочку вызовов. Однако, это соглашение может и нарушаться, особенно в коде на ассемблере или в коде, скомпилированном с оптимизацией)
  • 4. фрейм обработки исключений, на платформе Windows состоит из указателя на предыдущий фрейм обработки исключений и на функцию-обработчик исключений. В зависимости от реализации, число и местоположение этих фреймов может меняться, в том числе и во времени
  • 5. локальные переменные

Размер фрейма стека может динамически меняться в ходе работы программы до тех пор пока он в стеке остается верхним. Кроме того, в некоторых языках программирования есть специальные функции, которые не создают своих фреймов, а меняют родительский - так, на С/С++ этим "грешат" setjmp/longjmp и alloca

Вообще, фрейм стека создается самой подпрограммой в начале ее работы (это называется "пролог" подпрограммы) и уничтожается в конце (как называется - не знаю, "эпилог"?). Но, например, на ассемблере программист сам определяет поведение подпрограммы, да и на языках высокого уровня есть возможность отказаться от пролога (например, __declspec(naked) в Visual C/C++), так что создавать полный фрейм стека или нет - определяется решением программиста.

Но есть два элемента, которые программисту неподвластны - это первый и второй пункты, поскольку в стек они кладутся не вызываемой, а вызывающей подпрограммой (ну еще бы, откуда вызываемой подпрограмме о них вообще узнать, как не из стека). Подробности передачи этих двух элементов определяются такой вещью, как соглашение о вызове.

Так, соглашение о вызове cdecl, применяемое для функций языков C и C++, означает, что параметры в стек кладутся в обратном порядке, а извлекаются вызывающей подпрограммой. Это позволяет использовать подпрограммы с переменным числом аргументов, поскольку в таком случае первый параметр, отвечающий за количество аргументов, оказывается ближе всего к вершине стека, а, значит, расстояние между ним и вершиной стека постоянное. Это позволяет вызываемое подпрограмме его найти.

Как я уже сказал в самом начале, стеки существуют не у процессов, а у потоков. Это связано с тем, что для разных потоков цепочка вызовов подпрограмм может быть совершенно разной. Это не является неудобством, скорее это даже хорошо, поскольку позволяет для реализации переключения потоков просто подменять текущий указатель вершины стека, подменяя таким образом весь стек вызовов. Остальные величины (например, регистры процессора) явно сохранять и подменять не надо - достаточно сохранить их в стеке, а потом восстановить. Таким образом, если отбросить мишуру из маркеров безопасности, блокировок и прочего, то на принципиальном уровне поток - это всего лишь сохраненный указатель на вершину стека (в процессорах x86 - регистр esp или регистровая пара ss:esp)

источник = http://otvety.google.ru/otvety/thread?ti...