Переносимая функция в C (без сборки), которая возвращает размер кадра стека
Написать переносимую функцию в C (без сборки), которая возвращает размер кадра стека
int stackframe_size()
{
}
Попытка решить это, как показано ниже - Эта функция возвращает 228 байт при компиляции с VS 2010. Есть ли способ проверить ее правильность?
int stackframe_size(int run)
{
int i ;
if(!run)
{
return ((int)(&i) - stackframe_size(++run));
}
return (int)(&i);
}
Вызывается как:
int main()
{
printf("\nSize of stackframe_size() is: %d bytes",stackframe_size(0)) ;
return 0;
}
2 ответа
Такая портативная функция невозможна.
Ваша попытка, вероятно, примерно настолько близка, насколько вы можете получить, но вычитание указателя имеет неопределенное поведение. В более общем смысле, p1 - p0
, где p0
а также p1
являются указателями на различные объекты, имеет неопределенное поведение.
За исключением того, что ваш код вычитает int
значения, которые являются результатом преобразования из адресов. Прямое вычитание указателей с большей вероятностью сработает - и указатели должны быть типа char*
или же unsigned char*
, Есть много реализаций, где int
слишком мал, чтобы содержать преобразованный указатель, а некоторые, где указатели имеют более сложное представление, чем вы предполагаете, и преобразование их в даже достаточно большой целочисленный тип не обязательно даст вам значимый результат.
Существуют реальные реализации C, которые не используют "стек" в смысле непрерывной области памяти, в которой "кадры стека" помещаются и выталкиваются. (Должен быть "стек" в смысле структуры данных "первым пришел - последним вышел", но способ реализации "стека" совершенно не определен.) Некоторые реализации мэйнфреймов IBM, например, выделяют память для функции вызов через что-то вроде кучи, так что не существует определенной связи между адресами локальных переменных для двух таких вызовов.
Вероятно, вы можете написать функцию на чистом C (без ассемблера), которая дает размер стекового фрейма для конкретной реализации. Но поскольку сам язык C не имеет понятия "стековый фрейм" (в стандарте даже не используется слово "стек"), его нельзя сделать переносимым.
Я хотел проверить, есть ли умный / более чистый способ сделать это без добавления локальных переменных
Вы могли бы использовать &run
вместо &i
Это спасло бы вас от локальной переменной.
Есть ли способ проверить его правильность?
Используйте отладчик! Проверьте регистр указателя стека в местах, которые вас интересуют, посмотрите, как произошли разливы и т. Д.