Страниц: [1]
  Печать  
Автор Тема: адрес функции  (Прочитано 10666 раз)
Hed
Full Member
***
Offline Offline

Сообщений: 106



Просмотр профиля
« : Декабря 19, 2007, 09:28:46 pm »

Доброго времени суток.

Действие:
 функция А() вызвала функцию B()...
Задача:
 из функции B() нужно узнать адрес вызвавшей ее функции,  в данном случае функции A().

Подскажите как это делается или где читать...
Заранее спасибо.
Записан
AG
QOR.Moderator
*****
Offline Offline

Сообщений: 872



Просмотр профиля WWW
« Ответ #1 : Декабря 19, 2007, 10:59:35 pm »

никак. стандартных средств нет.

вопрос: а зачем? может есть проще решения...
Записан

Hed
Full Member
***
Offline Offline

Сообщений: 106



Просмотр профиля
« Ответ #2 : Декабря 20, 2007, 10:04:11 am »

Да может и есть, только пока в голове единственный вариант...

А суть в том, что через функцию B() идет управление неким ресурсом. Так вот в этой функции, в режиме отладки, хотелелось бы встроить трассировку/лог. Где будет записываться с какого адреса был вызов и с какими параметрами ресурс был изменен.

Очень не хочется каждый раз передавать адрес функции в качестве аргумента.
Записан
lastcross
Full Member
***
Offline Offline

Сообщений: 237


Просмотр профиля
« Ответ #3 : Декабря 20, 2007, 12:06:50 pm »

Очень трудно мне это ..представляется. Если трасировка не в дебагере - то что даст адрес метода? Я даже упускаю возможность всяких там DLL - где адрес насколько я понимаю у вас будет варьироватся от ДЛЛ к ДЛЛ .. и от приложения к приложению.. Даже если и адресса будут гарантировано постоянные - много гемора, имхо, по определению с какому именно адресу пренадлежит тот или иной вызов...
Если трасировка в дебагере - то поидее у него должна быть тулза.. которая показывает вызовы (обычно .. - адрес вызывающего метода помещается в стеке.. вопрос остался.. найти тулзу или развернуть стек самому). Но это работает как правило в месте "падения" (или по брекпоинту).
Записан
Hed
Full Member
***
Offline Offline

Сообщений: 106



Просмотр профиля
« Ответ #4 : Декабря 20, 2007, 07:57:13 pm »

To lastcross:

Немного я вас запутал, не уточнив некоторые моменты...

- рижим отладки - емеется ввиду не отладка в дебагере,
а режим работы самой программы в режиме отладки,

- OS QNX 4.25 - так что ни каких .dll, + компилятор саздает файл с картой адресов

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

- вся задумка ради того чтоб отследить "левые/лишние" обращения к ресурсам.
Записан
vshemm
Sr. Member
****
Offline Offline

Сообщений: 317


Просмотр профиля
« Ответ #5 : Декабря 21, 2007, 12:14:33 pm »

При входе в функцию В первый дворд на стеке будет указывать в функцию А. По идее Если вызов будет прямым, а не через "переходники".
Если вызовы должны происходить только из Ваших функций - делаете таблицу адресов (на этапе компиляции или в рантайме в случае перемещаемого кода) и сравниваете полученный адрес вызова с диапазонами из этой таблицы.
Записан
darkelf
QOR.Moderator
*****
Offline Offline

Сообщений: 259


Просмотр профиля
« Ответ #6 : Декабря 21, 2007, 04:06:51 pm »

Можно поступить следующим способом:
- создать структуру элемента массива истории, содержащего нужную Вам информацию о вызове (в простейшем варианте идентификатор функции)
- завести кольцевой массив истории;
- написать функцию трассировки - которая будет переписывать нужную Вам информацию в текущую позицию массива истории, и переходить к следующему, по достижении конца массива, переходить на первый элемент;
- написать функцию запроса n-го предыдущего вызова функции, которая относительно текущего указателя в кольцевом буфере будет возвращать запись, отстоящую на n
позиций назад;

в таком случае, если обе функции и A и B будут вызывать функцию трассировки, то функция B при помощи кольцевого буфера истории, может узнать, что её вызвала A.

Можно построить стек (программно), т.е. при входе в функцию вызывать, например, trace() (помещающую информацию в стек трассировки), а при выходе untrace()(удаляющую эту информацию). Стек трассировки строится аналогично таблице трассировки.
Записан
Hed
Full Member
***
Offline Offline

Сообщений: 106



Просмотр профиля
« Ответ #7 : Декабря 21, 2007, 07:39:51 pm »

Спасибо.
Буду корпеть.
Записан
lastcross
Full Member
***
Offline Offline

Сообщений: 237


Просмотр профиля
« Ответ #8 : Декабря 21, 2007, 09:53:06 pm »

Не.. ну если конешна.. код функций A и B доступен для изменения.. - то пожалуста.. Пишим свой класс-менеджер для хранения точек входа как синглтон CTraceManager.. Дальше делаем класс.. собствено организующий запись(удаления) в менеджер данных и тд. Назовем его CTracer .. Объект класса CTracer создаем статически в начале каждого метод. В конструкторе - указываем имя и параметры метода в котором он был создан (вплоть до адресса..вощем все необходимые параметры.. которые тебе нужны при разборе.. Главное чтобы один изних был уникальным .. для индетификации метода внутри менеджера - в простом варианте имя функции). При создании объекта - менеджеру передается параметры - и он создает нужную запись о входе в метод.
При выходе из метода - вызывается деструктор (объект статический.. потому он гарантировано вызовится ).. который обеспечивает уведомление менеджеру об выходе из метода.. Далее.. по завершению (а можно хоть и вовремя работы) - анализировать кто вызвал метод.. сколько раз.. зачем.. и в какой последовательности - все зависит от того как вы построите мендежер трасировок.. и от конкретной задачи..
Впринципе тоже самое что и писал darkelf - но на классы переведенное. А воще - это распространненый подход к логам. Но если не внутрьпрограммно (без доступа в сорцы) - то я тут немогу ниче подсказать ))
Записан
e_boris
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #9 : Декабря 22, 2007, 07:18:56 pm »

Если весь код доступен для компиляции, то можно использовать ключь wcc -ep (prologue hook) и свой prologue. Так, например, работает (работал ) deja-view.
Записан
Hed
Full Member
***
Offline Offline

Сообщений: 106



Просмотр профиля
« Ответ #10 : Декабря 23, 2007, 03:04:01 pm »

да, код весь доступен, но проект достаточно большой
и искать в нем все обращения к ресурсу достаточно тяжело. вот по этому и созрела идея вставить трассировку в функцию handler() этого ресурса.

Но, по всему видимо, придется искать... ))
Записан
lastcross
Full Member
***
Offline Offline

Сообщений: 237


Просмотр профиля
« Ответ #11 : Декабря 23, 2007, 03:44:04 pm »

Опять же не понятно - в чем рудность? Вставит в код каждой функции первой строчкой

#ifndef _DEBUG
  KTracer tracerObj(/*Имя функции и параметры функци,передающиеся менеджеру трасировки*/);
#endif // _DEBUG


..?? Как помне.. какой бы громадный проект бы небыл.. вставить одну строчку в каждую функцию.. нетак уж и времени займет. Я думаю чуть труднее(по затраченому времени) будет создать этот самый менеджер .. своими руками - но походу мона найти реализации и в инете
Записан
Hed
Full Member
***
Offline Offline

Сообщений: 106



Просмотр профиля
« Ответ #12 : Декабря 24, 2007, 11:03:16 am »

Да нету ни каких трудностей. )

Но, согласитесь, зачем измываться над всем кодом и над своим временем когда можно было бы акуратненько поправить только одно место. И из этого места наблюдать за всей работой.)
Была идея, была попытка, но...будем работать ручками ))
Записан
lastcross
Full Member
***
Offline Offline

Сообщений: 237


Просмотр профиля
« Ответ #13 : Декабря 24, 2007, 12:21:51 pm »

Всегда хочится - если править .. то только ОДНО место. )).
С таким подходом - только смотреть опции компилера как писал e_boris ито ..если этот компилер жутко "умный" и выдаст все что вам хотелось узнать. Ну и действительно - если время поджимает.
А так, как по мне, иметь в кармане клас типа KTracer .. вполне не помешало бы )). Сегодня потратите.. надцать единиц времени - завтра.. десяток минут на подобную задачу.
Записан
Страниц: [1]
  Печать  
 
Перейти в: