задачки про стек (программистское)
Sep. 17th, 2009 12:19 pm(эта запись будет интересна программистам, знающим C, и сочувствующим)
Две задачки - первая старая и известная, вторую только что придумал.
1. Напишите код на C, который определяет, в какую сторону растет стек на машине, где его запустили - вверх или вниз.
2. Напишите код на C, который проверяет, кто очищает стек от аргументов в конце работы функции - сама функция или тот, кто ее вызывает, после ее возвращения.
Обратите внимание, что обе задачи можно решить многими способами; интересней придумать решения, которые делают - по возможности, т.к. совсем без этого не обойтись - меньше предположений о том, как ведут себя компилятор и железо.
Комментарии скрывать не буду. Очень рекомендую подумать самому перед тем, как смотреть на решения там.
Две задачки - первая старая и известная, вторую только что придумал.
1. Напишите код на C, который определяет, в какую сторону растет стек на машине, где его запустили - вверх или вниз.
2. Напишите код на C, который проверяет, кто очищает стек от аргументов в конце работы функции - сама функция или тот, кто ее вызывает, после ее возвращения.
Обратите внимание, что обе задачи можно решить многими способами; интересней придумать решения, которые делают - по возможности, т.к. совсем без этого не обойтись - меньше предположений о том, как ведут себя компилятор и железо.
Комментарии скрывать не буду. Очень рекомендую подумать самому перед тем, как смотреть на решения там.
no subject
Date: 2009-09-17 09:38 am (UTC)На C++, наверное, можно проще, без вызова функций, так как можно что-то делать в промежутках между объявлениями переменных. Но вдруг компилятор захочет что-нибудь соптимизировать и переставить переменные. А с вызовом функции - практически гарантия.
no subject
Date: 2009-09-17 09:42 am (UTC)А вот вторая, как я понимаю, без привлечения знаний об устройстве компилятора неразрешима. Особенно если компилятор передает часть параметров через регистры.
no subject
Date: 2009-09-17 09:45 am (UTC)no subject
Date: 2009-09-17 09:51 am (UTC)no subject
Date: 2009-09-17 09:52 am (UTC)2. от локальных автоматических переменных всегда сама функция,
от переданных параметров всегда тот, кто вызывает (если речь идет о C).
Догадайтесь почему, и еще догадайтесь, зачем параметры пихаются
в обратном порядке :)
no subject
Date: 2009-09-17 09:52 am (UTC)no subject
Date: 2009-09-17 09:53 am (UTC)только один вариант (догадайтесь почему)
no subject
Date: 2009-09-17 09:54 am (UTC)no subject
Date: 2009-09-17 09:56 am (UTC)no subject
Date: 2009-09-17 09:59 am (UTC)no subject
Date: 2009-09-17 10:02 am (UTC)для функции с переменным чистом аргументов он
использован быть не может. Более того
обычный C не требует прототипов вызываемых функуций,
а stdcall без прототипов не возможен.
Так что речь о "pure С" не идёт.
no subject
Date: 2009-09-17 10:02 am (UTC)Из-за возможного разнобоя в количестве параметров стек либо должен чиститься вызывающей функцией, либо в стеке должен передаваться объем блока параметров (и тогда его может чистить вызванная функция). Различить эти два поведения программой на языке С невозможно: дополнительные поля в стековом кадре могут использоваться и для целей, не связанных с передачей параметров (например, сохраненные регистры или exception handlers в VMS/OS/2/Win32)
no subject
Date: 2009-09-17 10:03 am (UTC)no subject
Date: 2009-09-17 10:06 am (UTC)no subject
Date: 2009-09-17 10:07 am (UTC)no subject
Date: 2009-09-17 10:13 am (UTC)Скажем, в VMS (не только на ваксе) в блоке параметров всегда передается его размер.
Впрочем, в VMS, насколько я помню, стек всегда чистится вызывающей функцией, но по другой причине - там аргументы могут быть вообще не в стеке. :)
no subject
Date: 2009-09-17 10:19 am (UTC)no subject
Date: 2009-09-17 10:21 am (UTC)ЗЫ
Date: 2009-09-17 10:22 am (UTC)stdcall
The stdcall[1] calling convention is a variation on the pascal calling convention in which parameters are passed on the stack, pushed right-to-left. Registers EAX, ECX, and EDX are designated for use within the function. Return values are stored in the EAX register. The callee is responsible for cleanup of the stack.
Stdcall is the standard calling convention for the Microsoft Win32 API.
no subject
Date: 2009-09-17 10:23 am (UTC)2. единственное что приходит в голову — это проверить работает ли хвостовая рекурсия для функций с постоянным количеством аргументов. если работает, значит функции чистят за собой сами; если нет, то либо копилятор не фонтан, либо чистит зовущий. :)
no subject
Date: 2009-09-17 10:25 am (UTC)Re: ЗЫ
Date: 2009-09-17 10:33 am (UTC)I can't believe I'm participating in this jerkfest. Sheesh.
no subject
Date: 2009-09-17 10:33 am (UTC)2 - делаем следующим образом. Первым делом пишем две функции - первая возвращает current stack (адрес локальной переменной), вторая - dummy function без параметров.
Теперь делаем так - запоминаем current stack, затем вызываем dummy, которую кастингом приводим к функции с одним параметром. Затем снова вызываем current stack. Если оба раза стэк одинаков = мы его и чистим. Если стэк вырос - мы положились на вызываемую функцию.
Теперь осталось только подчистить за собой стек во втором случае.
(Метод не чистый, потому что посередине у нас есть участок кода, где стек не валидный, и теопретически это может нас грохнуть, но по идее там ничего нам из стека не надо...)
PS. А по идее, обе функции - current stack и dummy - могут быть одной и той же.
no subject
Date: 2009-09-17 10:35 am (UTC)int f(...) { return 0; }
int main() { f(1); f(1, 2); f(1, 2, 3); return 0; }
нельзя было бы корректно откомпилировать.
no subject
Date: 2009-09-17 10:39 am (UTC)Больше я с вами на эту тему общаться на буду, и если вы будете продолжать вести себя как тролль, забаню. У меня нет времени на пенисомерки.
По сути дела: стандарты C ничего не говорят про стек и способы передачи аргументов, поэтому говорить о "стандартном вызове" и "pure C" в контексте данной записи - нелепо. Кроме того, чистка стека фунцкией совместима
с переменным числом аргументов, просто требует предоставить функции информацию об их числе в каждом случае с помощью дополнительного скрытого бухгалтерского аргумента.