июля 15, 2009

Получаем стек в реальном времени

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

function BackTraceStrFunc(Addr: Pointer): ShortString;
Возвращает по адресу функции информацию о ней. В простейшем случае это будет просто адрес, а если скомпилировать программу с ключом -gl, то еще название этой функции и название файла, в котором она объявлена. В тот момент, когда программа падает и паскаль выводит стек вызовов - используется именно эта функция. Что забавно, это не функция, а переменная функционального типа, поэтому ее можно переопределить (BackTraceStrFunc := @MyBackTraceStrFunc;). Помимо адреса функции в нее можно передать информацию о вызове (см. get_caller_addr) и тогда будет выдан номер строки в исходнике, в которой был вызов.

function get_frame: pointer;
Возвращает указатель на фрейм вызова текущей функции. Сама по себе малополезна.

function get_caller_addr(framebp: pointer): pointer;
Возвращает указатель на место с информацией о том, откуда был вызван фрейм framebp. С помощью этого указателя уже можно получить при помощи BackTraceStrFunc информацию о вызывающей функции.

function get_caller_frame(framebp: pointer): pointer;
Возвращает фрейм, из которого был вызван фрейм framebp.

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

procedure PrintStack;
  var
    Frame: Pointer;
begin
  Frame := get_frame;
  while Frame <> nil do begin
    Writeln(BackTraceStrFunc(get_caller_addr(Frame)));
    Frame := get_caller_frame(Frame);
  end;
end;


Наслаждайтесь!


Комментариев нет:

Отправить комментарий

Постоянные читатели

Обо мне

Моя фотография
Мой e-mail: vitek_03(at)mail(dot)ru