2009-02-27 26 views
114

Giả sử C++ biên dịch hỗ trợ họ, là có bất kỳ lý do cụ thể không sử dụng __FILE__, __LINE____FUNCTION__ cho mục đích khai thác gỗ và gỡ lỗi?__FILE__, __LINE__, và sử dụng __FUNCTION__ trong C++

Tôi chủ yếu quan tâm đến việc cung cấp dữ liệu gây hiểu lầm cho người dùng — ví dụ: báo cáo số dòng hoặc chức năng không chính xác do kết quả tối ưu hóa hoặc kết quả đạt được hiệu suất.

Về cơ bản, tôi có thể tin tưởng __FILE__, __LINE____FUNCTION__-luôn làm điều đúng?

+0

__LINE__ nên làm điều đúng. Tôi đã sử dụng nó và nhóm thuần tập của nó, bao gồm __PRETTY_FUNCTION__. ... Nhưng ... ừm, tôi vừa mới nhìn vào mã nơi __LINE__ nằm. Có lẽ vì nó nằm trong khối catch để xử lý ngoại lệ try/catch. –

+2

có liên quan: [tham chiếu gcc cho các macro được xác định trước] (http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html) –

Trả lời

140

__FUNCTION__ không chuẩn, __func__ tồn tại trong C99/C++ 11. Những người khác (__LINE____FILE__) là tốt.

Nó sẽ luôn báo cáo đúng tệp và dòng (và chức năng nếu bạn chọn sử dụng __FUNCTION__/__func__). Tối ưu hóa là một yếu tố không phải vì nó là một mở rộng vĩ mô thời gian biên dịch; nó sẽ không bao giờ hiệu suất hiệu quả theo bất kỳ cách nào.

+2

'__func__' là một vấn đề trong C++. C99 không nói một từ về các đối số mặc định và vv, các trường hợp không rõ ràng như thế nào '__func__' sẽ hoạt động trong C++. – wilhelmtell

+3

@thr: trong khi bạn thực hiện một điểm tốt. Tôi đã khá rõ ràng rằng '__func__' tồn tại trong c99, không C++. Bất kể, tôi nghĩ rằng việc thực hiện hợp lý '__func__' trong C++ sẽ chỉ dẫn đến tên bị xáo trộn. Vì tôi không phải là một nhà biên dịch trình biên dịch, nó không thực sự là cuộc gọi của tôi. –

+0

Trình biên dịch nào không hỗ trợ '__FUNCTION__'? Trình biên dịch nào ngoại trừ gcc gần đây coi đây là biến, chứ không phải macro? – basin

7

Cá nhân, tôi miễn cưỡng sử dụng chúng cho bất cứ điều gì ngoài việc gỡ lỗi tin nhắn. Tôi đã làm điều đó, nhưng tôi cố gắng không hiển thị loại thông tin đó cho khách hàng hoặc người dùng cuối. Khách hàng của tôi không phải là kỹ sư và đôi khi không hiểu biết về máy tính. Tôi có thể đăng nhập thông tin này để bàn điều khiển, nhưng, như tôi đã nói, miễn cưỡng ngoại trừ gỡ lỗi xây dựng hoặc cho các công cụ nội bộ. Tôi cho rằng nó phụ thuộc vào cơ sở khách hàng mà bạn có.

+21

"Tôi có thể đăng nhập thông tin này lên bàn điều khiển" - hoặc tốt hơn: đăng nhập vào một tệp để nếu xảy ra sự cố, bạn có thể yêu cầu khách hàng gửi cho bạn ... – Christoph

30

Trong một số ít trường hợp, có thể hữu ích khi thay đổi dòng được cung cấp bởi __LINE__ thành một thứ khác. Tôi đã thấy GNU cấu hình làm điều đó cho một số xét nghiệm để báo cáo số dòng thích hợp sau khi nó chèn một số voodoo giữa các dòng không xuất hiện trong các tập tin nguồn gốc. Ví dụ:

#line 100 

sẽ làm cho các dòng sau bắt đầu với __LINE__ 100. Bạn có thể tùy chọn thêm một tập tin tên mới

#line 100 "file.c" 

Nó chỉ hiếm khi hữu ích. Nhưng nếu nó là cần thiết, không có lựa chọn thay thế tôi biết. Trên thực tế, thay vì dòng, một macro có thể được sử dụng quá mà phải dẫn đến bất kỳ của hai hình thức trên. Sử dụng thư viện tăng tiền xử lý, bạn có thể tăng dòng hiện bởi 50:

#line BOOST_PP_ADD(__LINE__, 50) 

tôi nghĩ rằng nó là hữu ích để đề cập đến nó, vì bạn hỏi về việc sử dụng __LINE____FILE__. Một không bao giờ đủ bất ngờ ra khỏi C++ :)

Edit: @ Jonathan Leffler cung cấp một số trường hợp sử dụng tốt hơn trong các ý kiến:

Rối tung với #line là rất hữu ích cho pre-vi xử lý mà muốn giữ các lỗi được báo cáo trong mã C của người dùng phù hợp với tệp nguồn của người dùng. Yacc, Lex, và (nhiều hơn ở nhà với tôi) ESQL/C preprocessor làm điều đó.

22

FYI: g ++ cung cấp macro __PRETTY_FUNCTION__ không chuẩn. Cho đến bây giờ tôi không biết về C99 __func__ (cảm ơn Evan!).Tôi nghĩ rằng tôi vẫn thích __PRETTY_FUNCTION__ hơn khi nó có sẵn cho phạm vi lớp phụ.

PS:

static string getScopedClassMethod(string thePrettyFunction) 
{ 
    size_t index = thePrettyFunction . find("("); 
    if (index == string::npos) 
    return thePrettyFunction; /* Degenerate case */ 

    thePrettyFunction . erase(index); 

    index = thePrettyFunction . rfind(" "); 
    if (index == string::npos) 
    return thePrettyFunction; /* Degenerate case */ 

    thePrettyFunction . erase(0, index + 1); 

    return thePrettyFunction; /* The scoped class name. */ 
} 
+0

Rất vui được biết về \ _ \ _ PRETTY_FUNCTION \ _ \ _. Rất hữu dụng! – Maverobot

4

Tôi sử dụng chúng mọi lúc. Điều duy nhất tôi lo lắng là cho IP trong các tệp nhật ký. Nếu tên chức năng của bạn thực sự tốt, bạn có thể làm cho một bí mật thương mại dễ dàng hơn để phát hiện ra. Nó giống như vận chuyển với các biểu tượng gỡ lỗi, chỉ khó tìm thấy mọi thứ hơn. Trong 99,999% các trường hợp không có gì xấu sẽ đến của nó.

+0

Điểm tốt để hiển thị. Nó là tầm thường để trích xuất thông tin này bằng cách sử dụng tiện ích 'strings' để trích xuất tất cả dữ liệu giống như chuỗi từ tệp thực thi. Ngay cả các tập tin thực thi nén cũng có thể được trích xuất. Hãy rất chú ý đến những gì bạn gửi đến một trang web của khách hàng. Thông thường các đối thủ cạnh tranh có thể có được bàn tay của họ trên thực thi của bạn, mặc dù họ không phải làm như vậy. – Marty

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