2010-07-23 34 views
5

Tôi đang tìm cách thông minh để theo dõi các cuộc gọi và trả về chức năng. Tôi biết tôi có thể sử dụng trình gỡ rối, nhưng tôi muốn một cách để chỉ in nó ra thiết bị đầu cuối khi gọi một hàm và phải bước qua mã.
Tôi nghĩ rằng tôi có thể sử dụng bộ tiền xử lý, nhưng tôi không chắc chắn điều gì sẽ là cách tốt nhất để thực hiện điều này.
Hoặc có cách nào để sử dụng gdb để in ra thông tin hữu ích, trong khi không phải bước qua mã.C/C++ cần một cách thông minh để theo dõi các cuộc gọi chức năng

Trả lời

2

Hoặc là có một cách để sử dụng gdb để in ra các thông tin mà sẽ có ích, trong khi không phải bước qua mã

Yes. Đặt điểm ngắt chỉ ở các hàm mà bạn thực sự quan tâm. Sử dụng "tiếp tục" cho đến khi bạn nhận được các chức năng đó hoặc cho đến khi chương trình của bạn bị treo. Sau đó sử dụng "backtrace" (hoặc "bt") để có được một dấu vết stack.

+0

Cảm ơn bạn đã quay lại, hoạt động tốt. –

3
#define BEGIN_FUNC(X) printf("Function %s Entered",X) 
#define END_FUNC(X) printf("Function %s End",X) 

foo() 
{ 
BEGIN_FUNC(__func__); 

//Your code here 


END_FUNC(__func__); 


} 

Tôi nghĩ nếu bạn viết macro như trên và sử dụng nó cho mọi chức năng như được mô tả thì bạn có thể nhận nhật ký trên thiết bị đầu cuối.

+0

+1 Câu trả lời của tôi thiếu – PostMan

+0

Điều này về cơ bản là cách lược tả xâm lấn thực hiện điều đó. –

+0

Đây là những gì tôi làm nhiều lần ... Một kỹ thuật tốt ... – Microkernel

0

Có một macro __FUNCTION__(Reference) được sử dụng để xác định phương thức nào (ở định dạng Class::Method) bạn đang tham gia, nhưng đây là quy trình thủ công hơn.

Tuy nhiên, khi tôi cần cùng một thông tin 'theo dõi' gần đây, tôi không thể tìm thấy phương pháp tự động.

2

Bạn có thể muốn xem Valgrind's Callgrind có thể theo dõi các cuộc gọi hàm thành biểu đồ đẹp. Nó sẽ hiển thị các cuộc gọi hàm, nhưng không hiển thị các tham số hoặc trả về giá trị.

13

Hầu hết các trình biên dịch đều cho phép bạn chèn một hàm thiết bị trước và sau khi thực hiện cuộc gọi hàm.

trong msvc họ _penter và _pexit
đẹp bài viết http://www.drdobbs.com/184403601

trong gcc bạn sẽ sử dụng -finstrument chức năng
http://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Code-Gen-Options.html

Bạn có thể sử dụng libaries debug hoặc các tập tin bản đồ để biết thêm thông tin .

+0

Bạn sẽ không xảy ra tp biết cách tìm kiếm hàm trong bảng biểu tượng trong gcc –

+0

Bạn có muốn tìm tên hoặc tra cứu mọi thứ không như các tham số vv trong các đối tượng gỡ lỗi? –

+0

Chỉ cần tên sẽ là tốt. #delay – reader

1

Nếu bạn cần tự động hóa, bạn có thể xem TARGET_ASM_FUNCTION_END_PROLOGUETARGET_ASM_FUNCTION_BEGIN_EPILOGUE. Đây là các trình biên dịch sẽ cho phép bạn chỉ định các phần của assembly được phát ra cùng với phần mở đầu của hàm bình thường - trong trường hợp của bạn, bạn sử dụng chúng để phát ra một assembly nhỏ để đăng nhập/thoát khỏi hàm đang được đề cập . Bạn cũng có thể xem FUNCTION_PROFILE và/hoặc PROFILE_HOOK (ví dụ: tại: http://gcc.gnu.org/onlinedocs/gccint/Function-Entry.html).

4

Một giải pháp khá phức tạp đang sử dụng RAII để kiểm soát phạm vi chức năng.Điều này sẽ có ảnh hưởng lớn trong hoạt động, nhưng sẽ khá rõ ràng trong các bản ghi mà không đòi hỏi người sử dụng thêm thiết bị đo đạc trong tất cả các đường dẫn mã có thể là có thể để lại các chức năng:

class ScopeLogger { 
public: 
    ScopeLogger(std::string const & msg) : msg(msg) 
    { std::cout << "Enter: " << msg << std::endl; } 
    ~ScopeLogger() 
    { std::cout << "Exit: " << msg << std::endl; } 
    std::string msg; 
}; 
#if DEBUG 
#define FUNCTION(x) ScopeLogger l_##x##_scope(x); 
#endif 

void foo(int value) { 
    FUNCTION(__FUNCTION__); 
    if (value > 10) throw std::exception; 
    std::cout << "." << std::endl; 
} 

int main() { 
    foo(0); // Enter: foo\n.\nExit: foo 
    foo(100); // Enter: foo\nExit: foo 
} 

Nếu mã là ren duy nhất, bạn thậm chí còn muốn thêm một biến tĩnh bằng một mức độ thụt đầu dòng để ScopedLogger mà không cần thêm là quá nhiều để ảnh hưởng hiệu suất đã nặng:

class ScopeLogger { 
public: 
    ScopeLogger(std::string const & msg) : msg(msg) 
    { std::cout << std::string(indent++,' ') << "Enter: " << msg << std::endl; } 
    ~ScopeLogger() 
    { std::cout << std::string(--indent,' ') << "Exit: " << msg << std::endl; } 
    std::string msg; 
    static int indent; 
}; 
int ScopeLogger::indent = 0; 
+0

Khá xâm nhập, nhưng ít hơn của Praveen. – Stephen

+0

Mã của bạn có biên dịch không? Trường hợp là contructor cho 'std :: string' để làm cho chuỗi' std :: (indent ++, "") 'hợp lệ? –

+0

@ bruce.banner: Tốt bắt, đó là những gì sẽ xảy ra khi bạn nhập vào một trang web thay vì trong một trình soạn thảo và biên dịch. Đối số thứ hai * phải là * một 'char', không phải là một' char * '(tức là tôi đã có nhầm lẫn gấp đôi trong đó dấu nháy đơn được yêu cầu). Ở bất kỳ mức nào, hãy sử dụng ý tưởng này như một ý tưởng, mã có các vấn đề khác, bao gồm nhưng có lẽ không giới hạn đối với an toàn luồng (hoặc thiếu nó). –

3

Vì bạn đang sử dụng GCC, bạn cũng có thể sử dụng trình liên kết chức năng gói.

Link-Time Replacement/Wrapping 
– GCC option: -Wl,--wrap,function_name 

Về cơ bản, bạn có thể thực hiện chức năng gọi là "__wrap_function_name()". Bạn có thể truy cập chức năng ban đầu bằng cách gọi "__real_function_name()".

0

Một thời gian trước, tôi đã nghe một cuộc trò chuyện về lập trình hướng đối tượng bao gồm những gì bạn muốn đạt được. Có lẽ một tìm kiếm cho thuật ngữ đó sẽ giúp.

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