studio - interfaz grafica en dev c++
Generar gráfico de llamadas para código C++ (6)
El "Analizador de C ++ Bsc" puede mostrar gráficos de llamadas, leyendo el archivo generado por la utilidad bscmake.
Intento generar un gráfico de llamadas con el que averiguar todas las posibles rutas de ejecución que están golpeando una función en particular (para no tener que descubrir todas las rutas manualmente, ya que hay muchas rutas que conducen a esta función). ) Por ejemplo:
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: ...
He intentado Codeviz y Doxygen, de alguna manera ambos resultados no muestran más que llamadas de la función objetivo, D. En mi caso, D es una función miembro de una clase cuyo objeto se ajustará dentro de un puntero inteligente. Los clientes siempre obtendrán el objeto del puntero inteligente a través de una fábrica para invocar a D.
¿Alguien sabe como lograr esto?
El cálculo estático de un gráfico preciso de llamadas de C ++ es difícil, ya que necesita un analizador de lenguaje preciso, una búsqueda correcta de nombres y un buen analizador de puntos que respete la semántica del lenguaje de forma adecuada. Doxygen no tiene ninguno de estos, no sé por qué las personas dicen que les gusta para C ++; es fácil construir un ejemplo de C ++ de 10 líneas que Doxygen analiza erróneamente).
Tal vez sea mejor que ejecute un generador de perfiles de tiempo que recolecta un gráfico de llamadas dinámicamente (esto describe el nuestro) y simplemente ejerce una gran cantidad de casos. Tales perfiladores le mostrarán el gráfico de llamada real ejercido.
EDITAR: de repente recordé Understand for C ++ , que afirma construir gráficos de llamadas. No sé qué usan para un analizador sintáctico, o si hacen el análisis detallado correcto; No tengo experiencia específica con su producto.
Estoy impresionado por la respuesta de Schaub, usando Clang; Esperaría que Clang tuviera todos los elementos correctos.
Para que el comando clang++
pueda encontrar archivos de encabezado estándar como mpi.h
, se deben usar dos opciones adicionales -### -fsyntax-only
, es decir, el comando completo debe verse como:
clang++ -### -fsyntax-only -S -emit-llvm main1.cpp -o - | opt -analyze -dot-callgraph
Puede lograr eso usando doxygen (con la opción de usar punto para la generación de gráficos).
Con Johannes Schaub - litb main.cpp, genera esto:
doxygen / dot es probablemente más fácil que clang / opt para instalar y ejecutar. No logré instalarlo yo mismo y es por eso que traté de encontrar una solución alternativa.
Puede usar CppDepend , puede generar muchos tipos de gráficos
- Gráfico de dependencia
- Call Graph
- Gráfico de herencia de clase
- Gráfico de acoplamiento
- Gráfico de ruta
- Gráfico de todas las rutas
- Gráfico de ciclo
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();
}
Entonces
$ clang++ -S -emit-llvm main1.cpp -o - | opt -analyze -dot-callgraph
$ dot -Tpng -ocallgraph.png callgraph.dot
Otorga una imagen brillante (hay un "nodo externo", porque main
tiene un enlace externo y podría ser llamado desde fuera de esa unidad de traducción también):
Es posible que desee posprocesar esto con c++filt
, de modo que pueda obtener los nombres no marcados de las funciones y clases involucradas. Como en el siguiente
#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
Otorga esta belleza (¡oh, el tamaño sin optimizaciones activadas era demasiado grande!)
Esa función mística sin nombre, Node0x884c4e0
, es un marcador de posición que se supone que es invocado por cualquier función cuya definición no se conoce.