Задача Трассировки (построение графа функций) - страница 2

 
sergeev:
Ведь одна и та же функция может вызываться как из start, так и из init. Вот это и надо фиксировать.

на пальцах могу, а конкретно -думать нуно ))

примерно так:

считаем кол-во ф-ций, пусть их будет 4, пишем в шапке кода #define X 4

предполагаем, что максимальное количество вызовов на одном тике будет #define Y 100

имеем матрицу размерностью 4 х 100, инициализируем матрицу = -1

и теперь при вызове ф-ции в точке входа в ф-цию добавляем вызов счетчика(формирователя графа) который должен добавлять при входе в нашу матрицу на свободную строку код(1,2,3 или 4) на нужную позицию Х -кто вызвал

думаю, что Ваша задача больше похожа на сетевые графики, подозреваю, что мат.аппарат для сетевых графиков давно разработан - нужно погуглить

ЗЫ: ну вотЪ ужо 2-я стр. топика ;)

 

IgorM, способ, который вы предлагаете для хранения графа называется "матрица смежности". Для разреженных графов он очень неэкономичен (да и за архитектуру "полносвязный граф" программистов нужно бить и т.д.)

Гораздо лучше использовать список рёбер (т.е. храним одномерный массив структур, состоящих из 2х элементов - id вызывающей функции и id вызываемой функции; структуру можно дополнить дополнительными полями - счётчиками вызовов и т.д.)

p.s. Матаппарат действительно давно разработан :)

 
lea:

IgorM, способ, который вы предлагаете для хранения графа называется "матрица смежности".

спс, хоть чтонить вспоминать начал, как никак ужо 15 лет прошло как изучал всю эту муть, которая в реальной жизни так и не пригодилась ))) - но не забывайте, что "упаковывание данных"(экономия памяти) - приведет к потере быстродействия из-за увеличения сложности мат.аппарата, хотя возможно я и ошибаюсь
 
MetaDriver:
Доказательство невозможности за идею проканает?
Логгирование входов- выходов из функций легко делается на С++,
там есть деструкторы и такая штучка как stack unwinding.
Хотя... для того же С++ есть библиотеки, которые для произвольной
точки в коде по стеку позволяют построить порядок вызова функций.
.
А так... каждый return означает дополнительные вызовы :-).
 
lea:
Дерево - частный случай графа.

да. это и имел ввиду. Исходя из линейности MQL кода - будет дерево в чистом виде. Так как вершины не будут указывать друг на друга.

IgorM:
имеем матрицу размерностью 4 х 100, инициализируем матрицу = -1
и теперь при вызове ф-ции в точке входа в ф-цию добавляем вызов счетчика(формирователя графа) который должен добавлять при входе в нашу матрицу на свободную строку код(1,2,3 или 4) на нужную позицию Х -кто вызвал

да. теперь понял. Но сдаётся мне этот подход действительно трудозатратный не столько в коде, сколько в в ресурсах и в подготовке к анализу. Для разветвления надо будет делать трехмерную матрицу.
В общем вариант принимается. Но пока что его оставим до 4 страницы на резюме :)

думаю, что Ваша задача больше похожа на сетевые графики, подозреваю, что мат.аппарат для сетевых графиков давно разработан - нужно погуглить

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

 
lea:

Гораздо лучше использовать список рёбер (т.е. храним одномерный массив структур, состоящих из 2х элементов - id вызывающей функции и id вызываемой функции; структуру можно дополнить дополнительными полями - счётчиками вызовов и т.д.)

Евгений, именно это уже и сделано.

Но стопор случился. Уже третий день ни спать, ни пить.... :)

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

 
sergeev:

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


И все одной только функцией, которая уже произвела проход вперед? Эт ты хватил - сделать возврат, ничего при этом не делая)) Ну ничего, уже вторая страничка закончилась, скоро Владимир не выдержит)))
 
alsu:
И все одной только функцией, которая уже произвела проход вперед? Эт ты хватил - сделать возврат, ничего при этом не делая)) Ну ничего, уже вторая страничка закончилась, скоро Владимир не выдержит)))

Бог с ними, с этими страницами. Задача ведь интересная.

Понимаете, тут как можно.... Откат на узел родителя можно делать уже в новом вызове потомка. То есть при переходе на потомка система сначала опустится по дереву на уровень ниже, а потом поднимется в нового вызванного потомка.

Но в этом варианте нельзя сделать ветки с глубиной более двух. Так как система всегда будет возвращаться назад перед походом вперед. То есть все функции будут рисоваться на одном уровне.

Поэтому думается, что придется использовать какие-то массивы переменных, для идентификации текущего положения. чтоб идти дальше, а не возвращаться. Вот именно в этом возврате и сложность...

 

В прицепе "концептуальная заготовка", точнее пример реализации. на MT 5

Чтоб до ума довести нужно функции in() и out() переписать, дабы заставить работать со списком вызовов. Сейчас они тупо распечатывают входы и выходы в стандартный поток.

Плохая новость: Мечту топикстартера об одной трассировочной функции я не сберёг. Прости Сергеев. :)

Хорошая новость: Всё работает.

Руководство пользователя.

1. В начале каждой функции вставляется макрос "_in"

2. Все вызовы return заменяются на "_return"

3. В начале проги прописывается два дефайна

#define _in in(__FUNCTION__);
#define _return out(__FUNCTION__);return


Собсно всё.

Файлы:
rettest.mq5  2 kb
 
sergeev:

Бог с ними, с этими страницами. Задача ведь интересная.

Понимаете, тут как можно.... Откат на узел родителя можно делать уже в новом вызове потомка. То есть при переходе на потомка система сначала опустится по дереву на уровень ниже, а потом поднимется в нового вызванного потомка.

Но в этом варианте нельзя сделать ветки с глубиной более двух. Так как система всегда будет возвращаться назад перед походом вперед. То есть все функции будут рисоваться на одном уровне.

Поэтому думается, что придется использовать какие-то массивы переменных, для идентификации текущего положения. чтоб идти дальше, а не возвращаться. Вот именно в этом возврате и сложность...

А откуда все таки такая странная задача? Стоит ли расходовать усилия на сомнительные изыскания, если можно элементарно сделать ДВЕ функции -на вход и выход - и не париться?
Причина обращения: