C ++ 코드에 대한 호출 그래프를 생성하는 방법
특정 함수에 도달하는 가능한 모든 실행 경로를 찾을 수있는 호출 그래프를 생성하려고합니다 (이 함수로 이어지는 경로가 많기 때문에 수동으로 모든 경로를 파악할 필요가 없습니다.) ). 예를 들면 :
path 1: A -> B -> C -> D
path 2: A -> B -> X -> Y -> D
path 3: A -> G -> M -> N -> O -> P -> S -> D
...
path n: ...
Codeviz와 Doxygen을 사용해 보았습니다. 두 결과 모두 대상 함수 D의 피 호출자 만 표시합니다. 제 경우 D는 객체가 스마트 포인터 내에 래핑되는 클래스의 멤버 함수입니다. 클라이언트는 D를 호출하기 위해 항상 팩토리를 통해 스마트 포인터 개체를 얻습니다.
누구든지 이것을 달성하는 방법을 알고 있습니까?
static void D() { }
static void Y() { D(); }
static void X() { Y(); }
static void C() { D(); X(); }
static void B() { C(); }
static void S() { D(); }
static void P() { S(); }
static void O() { P(); }
static void N() { O(); }
static void M() { N(); }
static void G() { M(); }
static void A() { B(); G(); }
int main() {
A();
}
그때
$ clang++ -S -emit-llvm main1.cpp -o - | opt -analyze -dot-callgraph
$ dot -Tpng -ocallgraph.png callgraph.dot
일부 반짝이는 그림을 생성합니다 ( main
외부 연결이 있고 해당 번역 단위 외부에서도 호출 될 수 있기 때문에 "외부 노드" 가 있습니다).
을 사용하여이를 후 처리 c++filt
할 수 있으므로 관련된 함수 및 클래스의 얽 히지 않은 이름을 얻을 수 있습니다. 다음과 같이
#include <vector>
struct A {
A(int);
void f(); // not defined, prevents inlining it!
};
int main() {
std::vector<A> v;
v.push_back(42);
v[0].f();
}
$ clang++ -S -emit-llvm main1.cpp -o - |
opt -analyze -std-link-opts -dot-callgraph
$ cat callgraph.dot |
c++filt |
sed 's,>,\\>,g; s,-\\>,->,g; s,<,\\<,g' |
gawk '/external node/{id=$1} $1 != id' |
dot -Tpng -ocallgraph.png
이 아름다움을 낳습니다 (오 마이, 최적화가 설정되지 않은 크기가 너무 큽니다!)
이 신비한 이름없는 함수 Node0x884c4e0
는 정의를 알 수없는 함수에 의해 호출되는 것으로 간주되는 자리 표시 자입니다.
doxygen (그래프 생성에 점을 사용하는 옵션 포함)을 사용하여이를 달성 할 수 있습니다.
Johannes Schaub-litb main.cpp를 사용하여 다음을 생성합니다.
doxygen / dot는 clang / opt보다 설치하고 실행하는 것보다 쉬울 것입니다. 내가 직접 설치하지 못했기 때문에 대체 솔루션을 찾으려고 노력했습니다!
Statically computing an accurate C++ call graph is hard, because you need a precise langauge parser, correct name lookup, and a good points-to analyzer that honors the language semantics properly. Doxygen doesn't have any of these, I don't know why people claim to like it for C++; it is easy to construct a 10 line C++ example that Doxygen erroneously analyzes).
You might be better off running a timing profiler which collects a call graph dynamically (this describes ours) and simply exercise a lot of cases. Such profilers will show you the actual call graph exercised.
EDIT: I suddenly remembered Understand for C++, which claims to construct call graphs. I don't know what they use for a parser, or whether they do the detailed analysis right; I have no specific experience with their product.
I am impressed by Schaub's answer, using Clang; I would expect Clang to have all the elements right.
You can use CppDepend, it can generates many kinds of graphs
- Dependency Graph
- Call Graph
- Class Inheritance Graph
- Coupling Graph
- Path Graph
- All Paths Graph
- Cycle Graph
In order for the clang++
command to find standard header files like mpi.h
two additional options should be used -### -fsyntax-only
, i.e. the full command should look as:
clang++ -### -fsyntax-only -S -emit-llvm main1.cpp -o - | opt -analyze -dot-callgraph
The "C++ Bsc Analyzer" can display call graphs - by reading the file generated by the bscmake utility.
doxygen + graphviz 는 콜 그래프를 생성하고 싶을 때 대부분의 문제를 해결할 수 있습니다.
Scitools Understand 는 내가 리버스 엔지니어링에 대해 아는 모든 것보다 뛰어난 환상적인 도구이며 고품질 그래프를 생성 합니다 .
그러나 그것은 매우 비싸고 평가판에는 나비 호출 그래프가 한 수준의 호출로만 제한되어 있다는 점에 유의하십시오 (IMHO 나는 그들이 그렇게하는 데 도움이되지 않는다고 생각합니다 ...)
참고 URL : https://stackoverflow.com/questions/5373714/how-to-generate-a-calling-graph-for-c-code
'development' 카테고리의 다른 글
Rails에서 force_ssl은 무엇을합니까? (0) | 2020.10.12 |
---|---|
어셈블리 (단위 테스트)가 다른 어셈블리의 내부 속성에 액세스하도록 허용하려면 어떻게합니까? (0) | 2020.10.12 |
Hubpipleline 외부에서 SignalR 허브 인스턴스를 사용하는 방법 (0) | 2020.10.12 |
VBA 배열 정렬 기능? (0) | 2020.10.12 |
QCombobox에서 선택한 값을 어떻게 얻을 수 있습니까? (0) | 2020.10.12 |