Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2017.05.21;
Скачать: CL | DM;

Вниз

Получить уровень вложенности кода.   Найти похожие ветки 

 
ВладОшин ©   (2016-04-29 09:59) [0]

Хочу получать уровень вложенности во время выполнения кода в процедурах/функциях..
Понимаю .что это совсем не тривиально. С др. стороны, наверняка есть инструмент, т.к. думаю часто нужно, да и реализуемо, принципиально

т.е. внутри процедуры что бы вызвать
ToLog("Сам напишу название" + IntToStr(Переменная_вложенности));
и
при коде
procA вызывает(->) procB -> procC -> procB
в лог записано
procA1
procB2
procC3
procB4

т.е .что-то подобное как в MSSQL переменная @@NESTLEVEL
Каждый раз, когда хранимая процедура вызывает другую хранимую процедуру или выполняет управляемый код путем обращения к подпрограмме, типу или статистическому выражению среды CLR, уровень вложенности возрастает.

Что было сделал - написал парсер, который просто после первого begin
вставлял инкремент глобальной переменной, а перед выходом - декремент, соотв. Натравил на исходники, переписал он мне их.
Но, ошибка уже очевидна - выход может быть не только в конце. Переписал все Exit; на begin dec(Lvl); Exit; end; Лучше, но тоже неправильно. Выход может быть по исключению.

Как бы "сесть" своим кодом на выход и вход в своих процедурах/функциях/методах?


 
Игорь Шевченко ©   (2016-04-29 10:24) [1]


> Хочу получать уровень вложенности во время выполнения кода
> в процедурах/функциях..


Зачем ?


> т.к. думаю часто нужно


За свои 30 с небольшим лет работы программистом не встречал надобности в таком знании...


 
ВладОшин ©   (2016-04-29 10:41) [2]


> Зачем ?

да есть зачем..

регулировать уровень расчетов. Если серверу будет тяжело, можно поставить максимум Ч, например. При rsltБузы или уровне вложенности Ч , дальнейшее уточнение результата считать несущественным

логгировать процесс в приятном виде:  уровень - кол-во табуляторов в начале строки


 
ВладОшин ©   (2016-04-29 10:42) [3]

пунто зло )
rsltБузы => rslt < eps


 
Kerk ©   (2016-04-29 10:47) [4]


> Но, ошибка уже очевидна - выход может быть не только в конце.

В try/finally оберни внутренности процедуры.


 
ВладОшин ©   (2016-04-29 11:15) [5]

сейчас про Эврику вспомнил
если подключить, то так можно

 ECS: TEurekaStackList;
 sLvl: string;
begin
 ECS := GetCurrentCallStack;
 sLvl := inttostr(ECS.Count);

но там безумные значение - 150, 160 )
оно и понятно - она все, наверное, считает, вроде как label.text := Fnc1()
- сначала getter метки, потом fnc, потом setter метки..


 
ВладОшин ©   (2016-04-29 11:23) [6]

хотя.. в принципе..
оно же меня не абсолютно интересует, а только возрастает или убывает "функция"


> В try/finally оберни

вариант, конечно
но хотелось бы изящнее  
всю свою лабуду стереть хочу
- ну, вроде inc на входе и dec на выходе и Exit => begin dec(Lvl); Exit; end


 
ВладОшин ©   (2016-04-29 11:55) [7]

эх, можно было бы, если ECS.Count > предыдущего, то +1, если меньше, то -1
но нет, не пойдет  
GetCurrentCallStack очень ресурсоемкий вызов, на фоне запросов к базе, даже простейших - не заметно, а когда чисто расчетные циклы, просто подсветить хотя бы внешний из циклов - все, интерфейс умер
например
время # тики # метка
11:48:41#     32 # -1
11:48:41#     47 # psOn
11:48:41#     46 # psOn
11:48:41#     63 # Enter
11:48:41#     62 # State

а ранее в тиках 0 было обычно

чудес не бывает, похоже )

пойду >> В try/finally оберни делать.. В принципе, интересующих процедур штук 50, не так и много
Думаю, если бы Розыч или Игорь что-то и присоветовали - было бы все равно неприемлимо по скорости в некоторых местах.

Спасибо )


 
Rouse_ ©   (2016-04-29 13:17) [8]

Я бы в принципе посоветовал вот в эту сторону смотреть: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680650(v=vs.85).aspx

но по скорости не тестировал, в моей утилите работает в принципе с устраивающей меня скоростью


 
DayGaykin ©   (2016-04-29 14:02) [9]


> Я бы в принципе посоветовал вот в эту сторону смотреть:
> https://msdn.microsoft.com/en-us/library/windows/desktop/ms680650(v=vs.
> 85).aspx

Неужели во время вызова call помимо того что в стек кладется адрес возврата, еще куда-то сохраняется информация о вызове?


 
Rouse_ ©   (2016-04-29 14:12) [10]

Не понял вопроса. Эта функция как раз данные со стека и раскручивает.


 
DayGaykin ©   (2016-04-29 14:25) [11]


> Rouse_ ©   (29.04.16 14:12) [10]

Так, а если я просто в стек положу адрес какой-то процедуры, то эта функция не отличит этот адрес от вызова?

К примеру, процедура:
procedure test(..., callback: pointer, ...); // Параметров такое количество, что бы callback передался через стек.

Внутри вызываем StackWalk64.
StackWalk64 определит что это просто параметр, а не вызов?


 
Игорь Шевченко ©   (2016-04-29 14:50) [12]

ВладОшин ©   (29.04.16 10:41) [2]

http://www.gunsmoker.ru/2008/10/x-y-z.html


 
KSergey ©   (2016-04-29 18:00) [13]

> ВладОшин ©   (29.04.16 11:15) [5]
>  ECS := GetCurrentCallStack;
>  sLvl := inttostr(ECS.Count);
>
> но там безумные значение - 150, 160 )
> оно и понятно - она все, наверное, считает, вроде как label. text := Fnc1()

Вашего кода не вижу, но 150, 160 видится странноватыми значениями.
У вас рекурсивный алгоритм?

А можно вообще поподробнее, но попонятнее рассказать как так вышло, что необходимо знать вложенность? рекурсивный алгоритм?


 
Rouse_ ©   (2016-04-29 18:34) [14]


> StackWalk64 определит что это просто параметр, а не вызов?

Должен по идее.
Параметры будут внутри стекового фрейма, адрес возврата на его границе.


 
DayGaykin ©   (2016-04-29 18:57) [15]


> Rouse_ ©   (29.04.16 18:34) [14]

Бегло почитал про стековый фрейм. Не понятно как функция может обнаружить его границу.


 
Pavia ©   (2016-04-29 20:17) [16]

Функция раскрутки начинает анализировать с себя. Она знает сколько у неё параметров и как они передаётся. Поэтому просто отнимает требуемое число параметров до границы.
Затем вычитает 4 байта. В стеке все параметры кратны 4 байта.
Там лежит адрес возврата.

Процедура переходит в некоторый код. Далее применяется функция обратной трассировки длины инструкций. Которая работает с 95% успехом.
В случае провала пробуется разные границы что доводит успех до 99%.
После восстановления начала функции. Анализируется уже тело. Выявляется число параметров в стеке. Тем самым получается вторая граница.
Потом анализируется конец функции. Выясняется тип вызова Far или не Near.

После второго вызова раскрутка продолжается с предыдущего шага.
Опять вычитается 4 байта или 8 для FAR.

Что-бы не мучиться с обратной трассировкой. Так как это не очень корректный метод применяются отладочные таблицы которые зашиты в конце PE файла.  Они передаются через параметр FuncTableEntry В них уже прописано для каждой функции её начало и конец функции, а также её тип и вроде количество параметров.


 
Kerk ©   (2016-04-29 22:44) [17]

Из пушки по воробьям по-моему.

Если тебе нужно остановить вычисления в тот момент, когда достигнута требуемая точность, то и нужно решать именно эту задачу, а не изобретать звездолет :)


 
ВладОшин ©   (2016-05-04 19:33) [18]

писал-писал, и ..закрыл окно (
Вот, жаль))

Да мне не нужен, пожалуй, стек знать.  Хотел схитрить.

>>Вашего кода не вижу, но 150, 160 видится странноватыми значениями.
Попробую коротко повторить
Код жив 17 лет, писался разными людьми. Некоторые, кроме первого, (по комментам сужу) не разбирались в коде, решая свою задачу на тот момент. Нотификаторы из нотификаторов + сообщения из сообщений - в общем, полное спагетти.
Иногда все это циклится, не понимаю пока почему.
Если не разбираться, то можно было бы выкрутится через уровень вложенности.
Но похоже, придется разбираться.


 
KSergey ©   (2016-05-05 10:12) [19]

О, кстати, еще вспомнил.
Все виндовые функции про раскрутку стека вызовов начинают абсолютно врать, выдавая неразумные значения, если по пути вызовов есть вложенные функции.
Может это как раз тот случай?

Как с этим справляются разные Eureka и справляются ли - не знаю.


 
KSergey ©   (2016-05-05 10:17) [20]

> ВладОшин ©   (04.05.16 19:33) [18]
> Иногда все это циклится, не понимаю пока почему.

Тогда 160 - это еще какое-то весьма малое значение )

Вероятно тут всё зависит от условий: один из вызовов (обработчиков сообщений) прерывает "зацикленность" по какому-то условию.
А дальше всё зависит от производительности процессора, особенностей разбора очереди в конкретной версии Windows и т.п. Если повезёт - то нужное сообощение, прерывающее цепь вечности, успеет обработаться, пока стек ен переполнился, если не повезёт - то не успевает.

(несколько притянуто за уши, конечно, при наличии лишь одного потока, понимаю; однако почему нет)



Страницы: 1 вся ветка

Текущий архив: 2017.05.21;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.005 c
8-1240901861
MathLamer
2009-04-28 10:57
2017.05.21
Быстрое преобразование Фурье 2D


15-1461762512
KSergey
2016-04-27 16:08
2017.05.21
Что такое Visual Studio Code ?


15-1461913150
ВладОшин
2016-04-29 09:59
2017.05.21
Получить уровень вложенности кода.


2-1441716490
TheEd
2015-09-08 15:48
2017.05.21
Что-то туплю с раскрашиванием строк TDBGrid(Eh)


15-1461842570
Pavia
2016-04-28 14:22
2017.05.21
Состоялся первый запуск с российского космодрома Восточный.