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보다 설치 및 실행하기가 더 쉬울 것입니다. 내가 직접 설치하지 않았기 때문에 대체 솔루션을 찾으려고 노력했습니다!


답변

정확한 C ++ 호출 그래프를 정적으로 계산하는 것은 어렵습니다. 정확한 언어 파서, 정확한 이름 조회 및 언어 의미 체계를 올바르게 준수하는 좋은 포인트 투 분석기가 필요하기 때문입니다. Doxygen에는 이러한 것들이 없습니다. 왜 사람들이 C ++를 좋아한다고 주장하는지 모르겠습니다. Doxygen이 잘못 분석하는 10 줄 C ++ 예제를 쉽게 구성 할 수 있습니다.)

호출 그래프를 동적으로 수집하고 (이것은 우리의 것을 설명 함) 단순히 많은 경우를 실행하는 타이밍 프로파일 러를 실행하는 것이 더 나을 수 있습니다 . 이러한 프로파일 러는 실행 된 실제 콜 그래프를 보여줍니다.

편집 : 갑자기 콜 그래프를 구성한다고 주장하는 C ++ 이해를 기억했습니다 . 나는 그들이 파서에 무엇을 사용하는지 또는 그들이 상세한 분석을 제대로하는지 여부를 모릅니다. 나는 그들의 제품에 대한 특별한 경험이 없습니다.

Clang을 사용한 Schaub의 답변에 감명을 받았습니다. 나는 Clang이 모든 요소를 ​​올바르게 갖기를 기대합니다.


답변

CppDepend 를 사용할 수 있으며 다양한 종류의 그래프를 생성 할 수 있습니다.

  • 종속성 그래프
  • 콜 그래프
  • 클래스 상속 그래프
  • 커플 링 그래프
  • 경로 그래프
  • 모든 경로 그래프
  • 사이클 그래프

여기에 이미지 설명 입력


답변

위해서는 clang++같은 표준 헤더 파일 찾기 명령 mpi.h이 추가 옵션을 사용해야 -### -fsyntax-only즉 전체 명령과 같이 보일 것입니다 :

clang++ -### -fsyntax-only -S -emit-llvm main1.cpp -o - | opt -analyze -dot-callgraph


답변

“C ++ Bsc Analyzer”는 bscmake 유틸리티에 의해 생성 된 파일을 읽어 호출 그래프를 표시 할 수 있습니다.


답변

doxygen + graphviz 는 콜 그래프를 생성하고 싶을 때 대부분의 문제를 해결할 수 있습니다.