Ответ 1
Если вы используете GNU, вы можете использовать функции backtrace. Вот пример использования этой справочной страницы.
Я использую цепочку инструментов gnu. Как я могу во время выполнения найти функцию функции? например, функция B() вызывается многими функциями с помощью указателей функций. Теперь, когда вызывается B, я хочу напечатать имя вызывающего абонента. Мне нужно это для отладки определенной проблемы.
Если вы используете GNU, вы можете использовать функции backtrace. Вот пример использования этой справочной страницы.
Расположение кода вызова вашей функции поддерживается gcc в __builtin_return_address()
. Чтобы получить имя для этого, вам необходимо проанализировать таблицу символов программы; в то время как это возможно, через dladdr()
, есть ограничения на это:
backtrace()
/dladdr()
(например, из обработчиков сигналов или одновременно в многопоточной программе или из контекстов, где вы не можете вызвать malloc()
.).backtrace()
), также как и для dladdr()
в разделе "ОШИБКИ" ).Это часто лучший способ разделить трассировку и определение имени функции; то есть просто вывести обратные адреса (как hex/binary), а затем обработать полученный журнал в соответствии с таблицей символов, полученной при запуске программы.
Другой метод, обозначенный Василем Димовым в ответ на аналогичный вопрос, заключается в замене вызова функции макросом-обертки, который сообщает или передает в вызывающей функции имя. Это будет работать с встроенными функциями, где backtrace не будет. С другой стороны, это не сработает, если вы вызываете функцию по ссылке или иным образом берете ее адрес.
Например:
int B(int x){
...
}
может стать:
int _B(int x, char *caller){
printf("caller is %s\n", caller);
...
}
#define B(x) _B((x), __func__)
и каждый вызов B() будет печатать имя вызывающего абонента. Василь Димов строит его по-другому, печатая имя непосредственно в макросе и оставляя функцию неизменной.