C ++ kodu için arama grafiği oluşturma


87

Belirli bir işleve ulaşan tüm olası yürütme yollarını bulmak için arama grafiği oluşturmaya çalışıyorum (böylece bu işleve götüren birçok yol olduğu için tüm yolları manuel olarak bulmam gerekmiyor. ). Örneğin:

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 ve Doxygen'i denedim, bir şekilde her iki sonuç da hedef fonksiyonun callees'inden başka bir şey göstermiyor, D. Benim durumumda, D, nesnesi akıllı bir göstericiye sarılacak olan bir sınıfın üye fonksiyonudur. Müşteriler, D'yi çağırmak için akıllı işaretçi nesnesini her zaman bir fabrika aracılığıyla elde edeceklerdir.

Bunu nasıl başaracağını bilen var mı?

Yanıtlar:


120
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();
}

Sonra

$ clang++ -S -emit-llvm main1.cpp -o - | opt -analyze -dot-callgraph
$ dot -Tpng -ocallgraph.png callgraph.dot

Parlak bir resim verir ("harici bir düğüm" vardır, çünkü mainharici bağlantıya sahiptir ve bu çeviri biriminin dışından da çağrılabilir):

Çağrı grafiği

Bunu ile sonradan işlemek isteyebilirsiniz c++filt, böylece ilgili işlevlerin ve sınıfların yönetilmemiş adlarını alabilirsiniz. Aşağıdaki gibi

#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    

Bu güzelliği sağlar (oh tanrım, optimizasyonların açılmadığı boyut çok büyüktü!)

Güzellik

Bu mistik isimsiz işlev, Node0x884c4e0tanımı bilinmeyen herhangi bir işlev tarafından çağrıldığı varsayılan bir yer tutucudur.


24
Bunu çok dosyalı bir projede mi yaptınız? bir araç olarak çok havalı görünüyor
dirvine

2
+1 Bazı nedenlerden dolayı, adların unmangle'ını kaldırmak için -n seçeneğini c ++ filt'ye geçirmek zorunda kaldım. Başka birinin aynı sorunla karşı karşıya kalması durumunda burada bahsedeceğimi düşündüm.
Aky

1
Bunu denerken bir hata alıyorum: Buna Pass::print not implemented for pass: 'Print call graph to 'dot' file'!ne diyorsunuz? clang 3.8
Arne

2
Buldum: -analyzeHerhangi bir nedenle seçeneği kaldırmam gerekiyor . Başka bir S: Çıktı dosya adını dışında başka bir şeye ayarlayabilir miyim ./callgraph.dot?
Arne

2
Sahip olduğum ikinci soru, bu komutu farklı dizinlerdeki birden çok dosya için nasıl çalıştırırım?
Acemi

18

Bunu doxygen kullanarak elde edebilirsiniz (grafikler oluşturmak için nokta kullanma seçeneğiyle).

görüntü açıklamasını buraya girin

Johannes Schaub - litb main.cpp ile bunu üretir:

görüntü açıklamasını buraya girin

doxygen / dot, clang / opt'in yüklenmesi ve çalıştırılmasından daha kolaydır. Kendim kurmayı başaramadım ve bu yüzden alternatif bir çözüm bulmaya çalıştım!


1
Dahil ettiğiniz pencereyi almak için doxygen'in nasıl çalıştırılacağına dair bir örnek ekleyebilir misiniz?
nimble_ninja

@nimble_ninja: Doxywizard yapılandırma iletişim kutusundaki ekran görüntüsü yeterli değil mi?
jpo38

1
Doxywizard'dan olduğunu bilmiyordum. Teşekkürler!
nimble_ninja

1
Şimdiye kadarki en iyi yöntem! :)
Leslie N

Büyük bir proje için pek uygun değil, 24 saat koştu, gigabaytlarca HTML dokümantasyonu, hala yapılmadı .. bunu atlamak. Sadece birkaç özel fonksiyon için arama grafiklerine ihtiyacım var (main () ile / arasında / arasında tam ağaç <=> SQL_COMMIT ()).
Gizmo

9

Doğru bir C ++ çağrı grafiğini statik olarak hesaplamak zordur, çünkü kesin bir dil ayrıştırıcısına, doğru ad aramasına ve dil anlamını doğru bir şekilde yerine getiren iyi bir noktadan analiz ediciye ihtiyacınız vardır. Doxygen bunlardan hiçbirine sahip değil, insanların neden C ++ için sevdiklerini iddia ettiklerini bilmiyorum; Doxygen'in hatalı olarak analiz ettiği 10 satırlık bir C ++ örneği oluşturmak kolaydır).

Dinamik olarak bir arama grafiği toplayan bir zamanlama profili oluşturucu çalıştırmanız daha iyi olabilir. (bu bizimkini açıklar) ve sadece birçok vakayı uygulayan bir . Bu tür profil oluşturucular size uygulanan gerçek arama grafiğini gösterecektir.

DÜZENLEME: Birden C ++ için Anlamayı hatırladım arama grafikleri oluşturduğunu iddia eden . Ayrıştırıcı için ne kullandıklarını veya ayrıntılı analizi doğru yapıp yapmadıklarını bilmiyorum; Ürünleriyle ilgili belirli bir deneyimim yok.

Schaub'ın Clang kullanarak verdiği yanıttan etkilendim; Clang'ın tüm unsurlara sahip olmasını beklerdim.


Ne yazık ki, bu işlevi tetikleyebilecek tüm kullanım durumlarının farkında değilim :(. Aslında, nihai amacım, bu işlevi hata ayıklama amacıyla kullanan kullanım durumlarının tam listesini bulmaktır. Bulabiliyorum. kod indeksleme aracına sahip doğrudan arayanlar, ancak daha fazla analiz için tüm yürütme yollarını
bulmaları gerekiyor

Öyleyse gerçekten istediğiniz, bir yöntemin çağrıldığı yürütme koşulu mu? Ardından, istenen yöntemle karşılaşılana kadar koşullu ifadeleri toplayarak, çağrı grafiğindeki çeşitli düğümlerde kontrol akışı boyunca ilerlemek için tam, doğru bir arama grafiğine ve bir aracın becerisine ihtiyacınız vardır. Bunu yapacak kullanıma hazır herhangi bir araç bilmiyorum (bu yorum sorudan 7 yıl sonra); bunu yapmak için muhtemelen özel bir analiz motoruna ihtiyacınız olacak. Clang buna sıkıştırılabilir; DMS araç setimiz bunun için kullanılabilir.
Ira Baxter

5

CppDepend'i kullanabilirsiniz , birçok türde grafik oluşturabilir

  • Bağımlılık Grafiği
  • Arama Grafiği
  • Sınıf Kalıtım Grafiği
  • Kaplin Grafiği
  • Yol Grafiği
  • Tüm Yollar Grafiği
  • Döngü Grafiği

görüntü açıklamasını buraya girin


3

clang++Komutun standart başlık dosyalarını bulabilmesi için mpi.hiki ek seçenek gibi kullanılması gerekir -### -fsyntax-only, yani tam komut şu şekilde görünmelidir:

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

1

"C ++ Bsc Analyzer", bscmake yardımcı programı tarafından oluşturulan dosyayı okuyarak arama grafiklerini görüntüleyebilir.


0

doxygen + graphviz , daha sonra insan gücüne verilen çağrı grafiği oluşturmak istediğimizde çoğu sorunu çözebilir.


0

Scitools anlayın bir olan fantastik bir araç, ben biliyorum her şeyi daha iyi ters mühendislik ve üretir kaliteli grafikler .

Ancak bunun oldukça pahalı olduğunu ve deneme sürümünün kelebek arama grafiğinin yalnızca bir arama seviyesi ile sınırlı olduğunu unutmayın (IMHO, bunu yaparken kendilerine yardımcı olmadıklarına inanıyorum ...)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.