Kodun resimli bir işlev çağrısı grafiğini [kapalı] almak için araçlar


107

C kodunun birçok kaynak dosyasının bulunduğu geniş bir çalışma alanım var. Nesne tarayıcısını kullanarak MS VS2005'teki bir işlevden ve MSVC 6.0'da da çağrılan işlevleri görebilsem de, bu yalnızca grafik olmayan bir ekranda belirli bir işlevden çağrılan işlevleri gösterir. Ek olarak, sözden başlayarak çağrılan işlevi main(), sonra ondan çağrılan işlevleri vb. Yaprak seviyesi işlevinin derinliklerinde göstermez.

Fonksiyonlar ile resimsel olarak bir fonksiyon çağırma grafiği verecek calleeve calleroklarla veya bunun gibi bir şeyle bağlanacak main(), fonksiyonun son seviyesinden başlayarak veya en azından bir C kaynak dosyasındaki tüm fonksiyonların bir çağrı grafiğini resimsel olarak gösteren bir araca ihtiyacım var. Bu grafiği yazdırabilirsem harika olur.

Bunu yapmak için herhangi bir iyi araç (ücretsiz araçlar olması gerekmez)?


Yanıtlar:



29

Dinamik analiz yöntemleri

Burada birkaç dinamik analiz yöntemini anlatıyorum.

Dinamik yöntemler aslında çağrı grafiğini belirlemek için programı çalıştırır.

Dinamik yöntemlerin tersi, programı çalıştırmadan tek başına kaynaktan belirlemeye çalışan statik yöntemlerdir.

Dinamik yöntemlerin avantajları:

  • işlev işaretlerini ve sanal C ++ çağrılarını yakalar. Bunlar önemsiz olmayan herhangi bir yazılımda çok sayıda bulunur.

Dinamik yöntemlerin dezavantajları:

  • programı çalıştırmanız gerekir, bu yavaş olabilir veya sahip olmadığınız bir kurulum gerektirebilir, örneğin çapraz derleme
  • yalnızca gerçekten çağrılan işlevler gösterilecektir. Örneğin, komut satırı argümanlarına bağlı olarak bazı işlevler çağrılabilir veya çağrılmayabilir.

KcacheGrind

https://kcachegrind.github.io/html/Home.html

Test programı:

int f2(int i) { return i + 2; }
int f1(int i) { return f2(2) + i + 1; }
int f0(int i) { return f1(1) + f2(2); }
int pointed(int i) { return i; }
int not_called(int i) { return 0; }

int main(int argc, char **argv) {
    int (*f)(int);
    f0(1);
    f1(1);
    f = pointed;
    if (argc == 1)
        f(1);
    if (argc == 2)
        not_called(1);
    return 0;
}

Kullanım:

sudo apt-get install -y kcachegrind valgrind

# Compile the program as usual, no special flags.
gcc -ggdb3 -O0 -o main -std=c99 main.c

# Generate a callgrind.out.<PID> file.
valgrind --tool=callgrind ./main

# Open a GUI tool to visualize callgrind data.
kcachegrind callgrind.out.1234

Artık birçok ilginç performans verisi içeren harika bir GUI programının içinde kaldınız.

Sağ alttaki "Arama grafiği" sekmesini seçin. Bu, işlevleri tıklattığınızda diğer pencerelerdeki performans ölçümleriyle ilişkilendirilen etkileşimli bir arama grafiğini gösterir.

Grafiği dışa aktarmak için sağ tıklayın ve "Grafiği Dışa Aktar" ı seçin. Dışa aktarılan PNG şu şekilde görünür:

Bundan şunu görebiliriz:

  • kök düğüm, _startgerçek ELF giriş noktasıdır ve glibc başlatma şablonunu içerir
  • f0, f1Ve f2birbirinden beklendiği gibi denir
  • pointedbir işlev göstericisi ile adlandırmamıza rağmen de gösterilmektedir. Bir komut satırı argümanı iletmiş olsaydık çağrılmamış olabilirdi.
  • not_called Ekstra bir komut satırı argümanı iletmediğimiz için çalıştırmada çağrılmadığı için gösterilmez.

Güzel olan yanı valgrind, herhangi bir özel derleme seçeneği gerektirmemesidir.

Bu nedenle, kaynak kodunuz olmasa bile, yalnızca çalıştırılabilir olanı kullanabilirsiniz.

valgrindkodunuzu hafif bir "sanal makine" üzerinden çalıştırarak bunu başarır. Bu aynı zamanda yürütmeyi yerel yürütmeye kıyasla oldukça yavaş hale getirir.

Grafikte görülebileceği gibi, her bir işlev çağrısı hakkında zamanlama bilgisi de elde edilir ve bu, yalnızca çağrı grafiklerini görmek için değil, muhtemelen bu kurulumun orijinal kullanım durumu olan programın profilini çıkarmak için kullanılabilir: Nasıl profil oluşturabilirim Linux üzerinde çalışan C ++ kodu?

Ubuntu 18.04'te test edildi.

gcc -finstrument-functions + etrace

https://github.com/elcritch/etrace

-finstrument-functions geri aramalar ekler , etrace ELF dosyasını ayrıştırır ve tüm geri aramaları uygular.

Ancak maalesef çalışmasını sağlayamadım : Neden "-finstrument-functions" bende çalışmıyor?

Talep edilen çıktı şu formattadır:

\-- main
|   \-- Crumble_make_apple_crumble
|   |   \-- Crumble_buy_stuff
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   |   \-- Crumble_buy
|   |   \-- Crumble_prepare_apples
|   |   |   \-- Crumble_skin_and_dice
|   |   \-- Crumble_mix
|   |   \-- Crumble_finalize
|   |   |   \-- Crumble_put
|   |   |   \-- Crumble_put
|   |   \-- Crumble_cook
|   |   |   \-- Crumble_put
|   |   |   \-- Crumble_bake

Muhtemelen, belirli donanım izleme desteğinin yanı sıra en verimli yöntemdir, ancak kodu yeniden derlemenizin dezavantajı vardır.


2
Dinamik arama grafiğinin programın yalnızca bir çalışmasını kapsadığını unutmayın.
smwikipedia

1
@smwikipedia evet, bunu daha net hale getirmek için cevabı yükselttim
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Burada ayrıca açıklanmıştır - stackoverflow.com/questions/311840/…
tauseef_CuriousGuy


9

Bizim DMS Yazılım Yeniden araç seti vardır , statik kontrol / veri akışı / puan arası / çağrı grafik analiz C kodu büyük sistemleri (~~ 25 milyon hat) uygulanmış, ve üretilen çağrı grafikler, işlev işaretçileri üzerinden çağrılabilir fonksiyonları da dahil olmak üzere .


1
Ah, güzel, 2016 yılı ve şimdi bir olumsuzluk ortaya çıkıyor. Eminim olumsuz oyu, bu aracın bunu yapamayacağına dair doğru bir değerlendirmeye dayanıyordu. Belki değil. Kesinlikle OP'nin istediği şeyi yapıyor.
Ira Baxter

1
Buna karşı çıkmak için olumlu oy alın. İşi bitirdiği sürece yazılımınız veya tescilli olması umrumda değil :-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功


5

Sen benim bash tabanlı C çağrı ağacı jeneratör kontrol edebilirsiniz burada . Arayan ve / veya bilgi aranmasını istediğiniz bir veya daha fazla C işlevini belirlemenize olanak tanır veya bir dizi işlev belirleyebilir ve bunları birbirine bağlayan işlev çağrılarının erişilebilirlik grafiğini belirleyebilirsiniz ... Yani bana ana ( ), foo () ve bar () bağlanır. Bir grafik motoru için graphviz / dot kullanır.


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.