2010-02-17 19 views
24

Tôi có mã nguồn của bên thứ 3 mà tôi phải điều tra. Tôi muốn nhìn thấy những gì đặt các chức năng được gọi nhưng tôi không muốn lãng phí thời gian đánh máy của tôi:Tự động thêm Nhật ký Chức năng Nhập/Thoát cho một Dự án

printf("Entered into %s", __FUNCTION__) 

printf("Exited from %s", __FUNCTION__) 

cho mỗi chức năng, cũng không làm tôi muốn chạm vào bất cứ nguồn nào tập tin.

Bạn có bất cứ đề xuất nào không? Có một lá cờ trình biên dịch tự động thực hiện điều này cho tôi?

Làm rõ cho nhận xét:

  • tôi sẽ chéo dịch chương trình nguồn để chạy nó trên ARM.
  • Tôi sẽ biên dịch nó bằng gcc.
  • Tôi không muốn phân tích mã tĩnh. Tôi muốn theo dõi thời gian chạy. Vì vậy, doxygen sẽ không làm cho cuộc sống của tôi dễ dàng hơn.
  • Tôi có nguồn và tôi có thể biên dịch nó.
  • Tôi không muốn sử dụng Lập trình hướng Aspect.

EDIT: Tôi thấy rằng lệnh 'khung' trong dấu nhắc gdb in khung hiện tại (hoặc, tên hàm, bạn có thể nói) tại thời điểm đó. Có lẽ, có thể (sử dụng các script gdb) để gọi lệnh 'frame' mỗi khi một hàm được gọi. Bạn nghĩ sao?

+0

Môi trường nào? – t0mm13b

+0

http://stackoverflow.com/questions/1173962/run-code-before-every-function-call-for-a-class-in-c/1174652 –

+0

@bmm: Bạn có nguồn cho bên thứ ba không bạn thực sự có thể biên dịch? – t0mm13b

Trả lời

26

Bên cạnh trình gỡ rối thông thường và các kỹ thuật lập trình hướng-khía cạnh, bạn cũng có thể chèn các chức năng thiết bị của riêng mình bằng cách sử dụng các tùy chọn dòng lệnh -finstrument-functions của gcc. Bạn sẽ phải triển khai các hàm __cyg_profile_func_enter()__cyg_profile_func_exit() của riêng mình (khai báo chúng dưới dạng extern "C" trong C++).

Chúng cung cấp phương tiện để theo dõi chức năng nào được gọi từ đâu. Tuy nhiên, giao diện hơi khó sử dụng vì địa chỉ của hàm đang được gọi và trang web cuộc gọi của nó được chuyển thay vì tên hàm, ví dụ. Bạn có thể đăng nhập các địa chỉ, và sau đó kéo các tên tương ứng từ bảng biểu tượng bằng cách sử dụng một cái gì đó như objdump --syms hoặc nm, giả sử tất nhiên các biểu tượng chưa bị tước khỏi các tệp nhị phân được đề cập.

Chỉ có thể dễ dàng sử dụng gdb. YMMV. :)

+0

Chính xác những gì tôi đang tìm :) –

+2

gcc FTW một lần nữa =) –

+0

mặc dù ... tôi nghĩ rằng loại điều này sẽ giới thiệu một chi phí đáng kể ngay cả khi tùy chỉnh trước/sau khi chức năng là trọng lượng nhẹ. –

1

Nếu bạn đang sử dụng gcc, cờ trình biên dịch ma thuật là -g. Biên dịch với các biểu tượng gỡ lỗi, chạy chương trình dưới gdb và tạo ra các dấu vết ngăn xếp. Bạn cũng có thể sử dụng ptrace, nhưng nó có thể dễ dàng hơn nhiều khi sử dụng gdb.

+0

Như tôi biết, theo dõi ngăn xếp là trạng thái của ngăn xếp cuộc gọi hàm tại một thời điểm cụ thể. Tôi có thể xuất các tên hàm của các hàm được gọi theo thứ tự vào một tệp bằng cách sử dụng tùy chọn ngăn xếp ngăn xếp trong gdb không? –

2

Đồng ý với William, sử dụng gdb để xem luồng thời gian chạy.
Có một số trình phân tích mã tĩnh có thể cho biết chức năng nào gọi và có thể cung cấp cho bạn một số biểu đồ lưu lượng cuộc gọi. Một công cụ là "Hiểu C++" (hỗ trợ C/C++) nhưng đó không phải là miễn phí tôi đoán. Nhưng bạn có thể tìm thấy các công cụ tương tự.

+0

thưa thớt, "trình phân tích cú pháp ngữ nghĩa", có tiện ích vẽ đồ thị. Nó tạo ra một tập tin graphviz có thể được chuyển đổi thành một hình ảnh. http://sparse.wiki.kernel.org/index.php/Main_Page –

+0

Cờ tùy chọn chính xác cho gdb là gì, nó sẽ cho phép nó in từng chức năng đang được gọi tại thời điểm đó? –

4

Sử dụng /Gh (Enable _penter Hook Function)/GH (Enable _pexit Hook Function) tắc biên dịch (nếu bạn có thể biên dịch các nguồn ofcourse)

Chú ý: bạn sẽ không thể sử dụng những vĩ mô của. See here ("bạn sẽ cần lấy địa chỉ hàm (trong thanh ghi EIP) và so sánh địa chỉ đó với địa chỉ trong tệp bản đồ có thể được tạo bởi trình liên kết (giả sử không có rebasing nào xảy ra). Nó sẽ rất chậm.")

+0

Cảm ơn PoweRoy. Bạn có biết cờ trình biên dịch tương ứng cho gcc không? Hoặc tên của kỹ thuật này, để tôi có thể google nó là gì? –

+0

Không biết gcc, '-g' của William trông giống nhau. Tôi đã tìm kiếm 'C++ enter/exit function hook' trên google: http://gcc.gnu.org/onlinedocs/gccint/Function-Entry.html – RvdK

11

Bạn đã nói "Tôi cũng không muốn chạm vào bất kỳ tệp nguồn nào" ... trò chơi công bằng nếu bạn để tập lệnh làm điều đó cho bạn?

Chạy ứng dụng này trên tất cả.file cpp

sed 's/^{/{ENTRY/' 

Vì vậy mà nó biến đổi chúng thành này:

void foo() 
{ENTRY 
    // code here 
} 

Đặt này trong một tiêu đề có thể đượC#included bởi tất cả các đơn vị:

#define ENTRY EntryRaiiObject obj ## __LINE__ (__FUNCTION__); 

struct EntryRaiiObject { 
    EntryRaiiObject(const char *f) : f_(f) { printf("Entered into %s", f_); } 
    ~EntryRaiiObject() { printf("Exited from %s", f_); } 
    const char *f_; 
}; 

Bạn có thể phải được fancier với tập lệnh sed. Bạn cũng có thể đặt macro ENTRY ở bất kỳ nơi nào khác mà bạn muốn thăm dò, giống như một số phạm vi bên trong lồng nhau sâu sắc của một hàm.

+6

Bạn có thể có nhiều thứ bắt đầu bằng '{' trong đầu của một dòng: cấu trúc, v.v. Làm cách nào để bạn nhắm mục tiêu các hàm đáng tin cậy? – lalebarde

Các vấn đề liên quan