Вот две опции:
можно получить полный stacktrace (включая имя, модуль и смещение функции вызова) с последними версиями glibc с функции следа GNU . См. мой ответ здесь для деталей. Это - вероятно, самая легкая вещь.
, Если это не точно, что Вы ищете, тогда Вы могли бы попробовать libunwind, но он собирается включить больше работы.
Имеют в виду, что это не что-то, что можно знать статически (как с PRETTY_FUNCTION); на самом деле необходимо обойти стек для выяснения то, что функция позвонила Вам. Таким образом, это не что-то, что это действительно стоит сделать в обычной отладке printfs. Если Вы хотите сделать более серьезную отладку или анализ, тем не менее, тогда, это могло бы быть полезно для Вас.
Вот решение, которое можно часто использовать. Это имеет преимущество требования никаких изменений в фактическом функциональном коде (, никакое добавление не звонит в функции прохода по стеку, изменение параметров для передачи на имена функций или соединение с дополнительными библиотеками. ). Для получения его работа просто необходимо использовать немного волшебства препроцессора:
// orignal function name was 'FunctionName'
void FunctionNameReal(...)
{
// Do Something
}
#undef FunctionName
#define FunctionName printf("Calling FunctionName from %s\n",__FUNCTION__);FunctionNameReal
необходимо переименовать функцию временно, но видеть примечание ниже для большего количества предложений. Это приведет к printf()
оператор в каждой точке вызывания функции. Очевидно, необходимо сделать некоторые приготовления, если Вы называете функцию членства или должны получить возвращаемое значение ( Как передача вызов функции и __FUNCTION__
к пользовательской функции, которая возвращает тот же тип... ), но основная техника является тем же. Вы могли бы хотеть использовать __LINE__
и __FILE__
или некоторые другие макросы препроцессора, в зависимости от которых компилятора Вы имеете. (Этот пример специально для VC MS ++, но вероятно работает в других.)
кроме того, Вы могли бы хотеть поместить что-то вроде этого в свой заголовок, окруженный [1 110] защита для условного включения его, который может обработать переименование фактической функции для Вас также.
я заставил запрос разворачивать мой ответ. Как оказалось, мой выше примера немного упрощен. Вот некоторые полностью компилирующие примеры обработки этого, с помощью C++.
Используя class
с [1 112] делает это довольно прямым. Эта первая техника работает на автономные функции с и без возвращаемых значений. operator()
просто потребности отразить тот же возврат как рассматриваемая функция, и иметь соответствие аргументам.
можно скомпилировать это с [1 114] для версии несоздания отчетов и g++ -o test test.cpp -DREPORT
для версии, которая отображает информацию о вызывающем абоненте.
#include <iostream>
int FunctionName(int one, int two)
{
static int calls=0;
return (++calls+one)*two;
}
#ifdef REPORT
// class to capture the caller and print it.
class Reporter
{
public:
Reporter(std::string Caller, std::string File, int Line)
: caller_(Caller)
, file_(File)
, line_(Line)
{}
int operator()(int one, int two)
{
std::cout
<< "Reporter: FunctionName() is being called by "
<< caller_ << "() in " << file_ << ":" << line_ << std::endl;
// can use the original name here, as it is still defined
return FunctionName(one,two);
}
private:
std::string caller_;
std::string file_;
int line_;
};
// remove the symbol for the function, then define a new version that instead
// creates a stack temporary instance of Reporter initialized with the caller
# undef FunctionName
# define FunctionName Reporter(__FUNCTION__,__FILE__,__LINE__)
#endif
void Caller1()
{
int val = FunctionName(7,9); // <-- works for captured return value
std::cout << "Mystery Function got " << val << std::endl;
}
void Caller2()
{
// Works for inline as well.
std::cout << "Mystery Function got " << FunctionName(11,13) << std::endl;
}
int main(int argc, char** argv)
{
Caller1();
Caller2();
return 0;
}
Демонстрационный Вывод (Сообщая)
Reporter: FunctionName() is being called by Caller1() in test.cpp:44
Mystery Function got 72
Reporter: FunctionName() is being called by Caller2() in test.cpp:51
Mystery Function got 169
В основном, где угодно это FunctionName
происходит, он заменяет его [1 117], результирующий эффект которого является препроцессором, пишущий некоторое инстанцирование объекта с непосредственным вызовом к эти operator()
функция. Можно просмотреть результат (в gcc) замен препроцессора с [1 119]. Caller2 () становится этим:
void Caller2()
{
std::cout << "Mystery Function got " << Reporter(__FUNCTION__,"test.cpp",51)(11,13) << std::endl;
}
Вы видите, что __LINE__
и __FILE__
были заменены. (Я не уверен, почему __FUNCTION__
все еще шоу в выводе честно говоря, но скомпилированная версия сообщает о правильной функции, таким образом, это, вероятно, имеет некоторое отношение к многопроходной предварительной обработке или gcc ошибке.)
Класса Это немного более сложно, но очень похоже на предыдущий пример. Вместо того, чтобы просто заменить вызов к функции, мы также заменяем класс.
Как вышеупомянутый пример, можно скомпилировать это с [1 123] для версии несоздания отчетов и g++ -o test test.cpp -DREPORT
для версии, которая отображает информацию о вызывающем абоненте.
#include <iostream>
class ClassName
{
public:
explicit ClassName(int Member)
: member_(Member)
{}
int FunctionName(int one, int two)
{
return (++member_+one)*two;
}
private:
int member_;
};
#ifdef REPORT
// class to capture the caller and print it.
class ClassNameDecorator
{
public:
ClassNameDecorator( int Member)
: className_(Member)
{}
ClassNameDecorator& FunctionName(std::string Caller, std::string File, int Line)
{
std::cout
<< "Reporter: ClassName::FunctionName() is being called by "
<< Caller << "() in " << File << ":" << Line << std::endl;
return *this;
}
int operator()(int one, int two)
{
return className_.FunctionName(one,two);
}
private:
ClassName className_;
};
// remove the symbol for the function, then define a new version that instead
// creates a stack temporary instance of ClassNameDecorator.
// FunctionName is then replaced with a version that takes the caller information
// and uses Method Chaining to allow operator() to be invoked with the original
// parameters.
# undef ClassName
# define ClassName ClassNameDecorator
# undef FunctionName
# define FunctionName FunctionName(__FUNCTION__,__FILE__,__LINE__)
#endif
void Caller1()
{
ClassName foo(21);
int val = foo.FunctionName(7,9); // <-- works for captured return value
std::cout << "Mystery Function got " << val << std::endl;
}
void Caller2()
{
ClassName foo(42);
// Works for inline as well.
std::cout << "Mystery Function got " << foo.FunctionName(11,13) << std::endl;
}
int main(int argc, char** argv)
{
Caller1();
Caller2();
return 0;
}
Вот демонстрационный вывод:
Reporter: ClassName::FunctionName() is being called by Caller1() in test.cpp:56
Mystery Function got 261
Reporter: ClassName::FunctionName() is being called by Caller2() in test.cpp:64
Mystery Function got 702
звездные часы этой версии являются классом, который украшает исходный класс и заменяющую функцию, которая возвращает ссылку на экземпляр класса, позволяя operator()
делать фактический вызов функции.
Hope, которая помогает кому-то!
В приближении елей, просто grep кодовая база для имен функций. Тогда прибывает Doxygen, и затем динамический вход (оба обсужденные другими).
Вы, вероятно, хотите названия всех функций, которые потенциально могли назвать их. Это - в основном ряд краев в графе вызовов. doxygen может генерировать граф вызовов, и затем это - просто вопрос рассмотрения входящих краев Вашего узла функций.