วิธีสร้างกราฟการโทรสำหรับรหัส C ++


87

ฉันกำลังพยายามสร้างกราฟการโทรเพื่อค้นหาเส้นทางการดำเนินการที่เป็นไปได้ทั้งหมดที่มีการกดปุ่มฟังก์ชันเฉพาะ (เพื่อที่ฉันจะได้ไม่ต้องค้นหาเส้นทางทั้งหมดด้วยตนเองเนื่องจากมีหลายเส้นทางที่นำไปสู่ฟังก์ชันนี้ ). ตัวอย่างเช่น:

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

ไม่มีใครรู้วิธีการบรรลุนี้?

คำตอบ:


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

แล้ว

$ 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นั้นเป็นตัวยึดที่สมมติว่าเรียกโดยฟังก์ชันใด ๆ ที่ไม่ทราบคำจำกัดความ


24
คุณได้ทำสิ่งนี้กับโครงการหลายไฟล์หรือไม่? ดูเท่มากในฐานะเครื่องมือ
dirvine

2
+1 ด้วยเหตุผลบางอย่างฉันต้องส่งตัวเลือก -n ไปยัง c ++ filt เพื่อให้ชื่อคลายความยุ่งเหยิง คิดว่าฉันจะพูดถึงที่นี่ในกรณีที่มีคนอื่นประสบปัญหาเดียวกัน
Aky

1
ฉันได้รับข้อผิดพลาดเมื่อลองสิ่งนี้: Pass::print not implemented for pass: 'Print call graph to 'dot' file'!เกิดอะไรขึ้น? เสียงดัง 3.8
Arne

2
พบแล้ว: ฉันต้องลบ-analyzeตัวเลือกนี้ออกด้วยเหตุผลบางประการ คำถามอื่น: ฉันสามารถตั้งชื่อไฟล์เอาต์พุตเป็นอย่างอื่นได้./callgraph.dotหรือไม่?
Arne

2
คำถามที่สองฉันมีวิธีเรียกใช้คำสั่งนี้สำหรับไฟล์หลายไฟล์ในไดเรกทอรีที่แตกต่างกันได้อย่างไร
Newbie

18

คุณสามารถทำได้โดยใช้ doxygen (พร้อมตัวเลือกในการใช้จุดสำหรับการสร้างกราฟ)

ใส่คำอธิบายภาพที่นี่

ด้วย Johannes Schaub - litb main.cpp จะสร้างสิ่งนี้:

ใส่คำอธิบายภาพที่นี่

doxygen / dot อาจง่ายกว่าการส่งเสียงดัง / เลือกที่จะติดตั้งและเรียกใช้ ฉันไม่ได้จัดการติดตั้งด้วยตัวเองและนั่นคือเหตุผลที่ฉันพยายามหาทางเลือกอื่น!


1
คุณสามารถเพิ่มตัวอย่างวิธีการเรียกใช้ doxygen เพื่อรับหน้าต่างที่คุณรวมไว้ได้หรือไม่?
nimble_ninja

@nimble_ninja: ภาพหน้าจอจากกล่องโต้ตอบการกำหนดค่า doxywizard ไม่เพียงพอหรือไม่
jpo38

1
ฉันไม่รู้ว่ามันมาจาก doxywizard ขอบคุณ!
nimble_ninja

1
วิธีที่ดีที่สุด! :)
Leslie N

ใช้งานไม่ได้จริงสำหรับโปรเจ็กต์ขนาดใหญ่ใช้งานเอกสาร HTML เป็นเวลา 24 ชม. ยังไม่เสร็จ .. ข้ามอันนี้ไป ฉันต้องการเรียกกราฟสำหรับฟังก์ชันเฉพาะบางอย่าง (โครงสร้างที่สมบูรณ์ถึง / จาก / ระหว่าง main () <=> SQL_COMMIT ())
Gizmo

9

การคำนวณกราฟการเรียก C ++ ที่แม่นยำแบบคงที่เป็นเรื่องยากเนื่องจากคุณต้องมีตัวแยกวิเคราะห์ภาษาที่แม่นยำการค้นหาชื่อที่ถูกต้องและตัววิเคราะห์จุดที่ดีที่ให้ความสำคัญกับความหมายของภาษาอย่างเหมาะสม Doxygen ไม่มีสิ่งเหล่านี้ฉันไม่รู้ว่าทำไมคนถึงอ้างว่าชอบ C ++; เป็นเรื่องง่ายที่จะสร้างตัวอย่าง C ++ 10 บรรทัดที่ Doxygen วิเคราะห์ผิดพลาด)

คุณอาจจะดีกว่าถ้าเรียกใช้ตัวกำหนดเวลาซึ่งรวบรวมกราฟการโทรแบบไดนามิก (ซึ่งอธิบายถึงของเรา) และใช้หลาย ๆ กรณี ผู้สร้างโปรไฟล์ดังกล่าวจะแสดงกราฟการโทรจริงที่ใช้

แก้ไข: ทันใดนั้นฉันก็จำได้ เข้าใจสำหรับ C ++ซึ่งอ้างว่าสร้างกราฟการโทร ฉันไม่รู้ว่าพวกเขาใช้โปรแกรมแยกวิเคราะห์อะไรหรือว่าพวกเขาวิเคราะห์โดยละเอียดหรือไม่ ฉันไม่มีประสบการณ์เฉพาะกับผลิตภัณฑ์ของพวกเขา

ฉันประทับใจกับคำตอบของ Schaub โดยใช้เสียงดัง ฉันคาดหวังว่า Clang จะมีองค์ประกอบที่ถูกต้องทั้งหมด


น่าเสียดายที่ฉันไม่ทราบถึงกรณีการใช้งานทั้งหมดที่อาจทริกเกอร์ฟังก์ชันนั้น :( อันที่จริงเป้าหมายสูงสุดของฉันคือการค้นหารายการกรณีการใช้งานที่แน่นอนซึ่งใช้ฟังก์ชันนั้นเพื่อการดีบักฉันสามารถหาคำตอบได้ ผู้โทรโดยตรงที่มีเครื่องมือสร้างดัชนีรหัส แต่จำเป็นต้องหาเส้นทางการดำเนินการทั้งหมดเพื่อการวิเคราะห์เพิ่มเติม
shiouming

ดังนั้นสิ่งที่คุณต้องการจริงๆคือเงื่อนไขการดำเนินการภายใต้วิธีการที่เรียกว่า? จากนั้นคุณต้องมีกราฟการโทรที่สมบูรณ์และแม่นยำและความคลาดเคลื่อนของเครื่องมือเพื่อเดินไปตามโฟลว์การควบคุมในโหนดต่างๆในกราฟการโทรรวบรวมนิพจน์เงื่อนไขจนกว่าจะพบเมธอดที่ต้องการ ฉันไม่รู้ว่ามีเครื่องมือนอกชั้นวางที่จะทำสิ่งนี้ได้ (ความคิดเห็นนี้ช้ากว่าคำถาม 7 ปี) คุณอาจต้องมีเครื่องมือวิเคราะห์ที่กำหนดเองเพื่อทำสิ่งนี้ เสียงดังอาจถูกกดลงในสิ่งนี้ ชุดเครื่องมือ DMS ของเราสามารถใช้สำหรับสิ่งนี้
Ira Baxter

5

คุณสามารถใช้CppDependซึ่งสามารถสร้างกราฟได้หลายประเภท

  • กราฟการพึ่งพา
  • โทรกราฟ
  • กราฟการสืบทอดคลาส
  • กราฟการมีเพศสัมพันธ์
  • กราฟเส้นทาง
  • กราฟเส้นทางทั้งหมด
  • กราฟวงจร

ใส่คำอธิบายภาพที่นี่


3

เพื่อให้clang++คำสั่งค้นหาไฟล์ส่วนหัวมาตรฐานเช่นmpi.hควรใช้สองตัวเลือกเพิ่มเติม-### -fsyntax-onlyกล่าวคือคำสั่งเต็มควรมีลักษณะดังนี้:

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



0

Scitools เข้าใจเป็นเครื่องมือที่ยอดเยี่ยมดีกว่าทุกสิ่งที่ฉันรู้สำหรับวิศวกรรมย้อนกลับและสร้างกราฟคุณภาพสูงกราฟที่มีคุณภาพสูง

แต่โปรดทราบว่ามันค่อนข้างแพงและเวอร์ชันทดลองมีกราฟการเรียกผีเสื้อที่จำกัด การโทรเพียงระดับเดียว (IMHO ฉันเชื่อว่าพวกเขาไม่ได้ช่วยตัวเองในการทำเช่นนั้น ... )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.