Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2017.05.21;
Скачать: [xml.tar.bz2];

Вниз

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

 
ВладОшин ©   (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;
Скачать: [xml.tar.bz2];

Наверх





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


15-1461854802
Германн
2016-04-28 17:46
2017.05.21
Существует ли такая VM, которая знает что такое LPT-порт?


15-1460557855
DSKalugin
2016-04-13 17:30
2017.05.21
Жизненный цикл программиста :-)


8-1240992981
Diha
2009-04-29 12:16
2017.05.21
Воспройзведение видео с помощью Дельфи


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





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский