2012-12-03 19 views
13

thể trùng lặp:
What is the point of the Noreturn attribute?Sử dụng _Noreturn trong C11

C11 giới thiệu các thuộc tính _Noreturn để cho biết rằng một chức năng không bao giờ trở lại.

Ngoại trừ giá trị tài liệu trong mã nguồn, các thuộc tính khác cung cấp những lợi ích nào và tại sao một thuộc tính sẽ sử dụng?

+1

http://stackoverflow.com/questions/10538291/what-is-the-point-of-the-noreturn-attribute sẽ hỏi cùng một câu hỏi cho C++. Lý do cho C là chính xác như nhau. –

+3

Lý do tương tự; cú pháp có vẻ khác hoàn toàn giữa C++ ('[[noreturn]]') và C ('_Noreturn' hoặc' noreturn' nếu bạn đã bao gồm ''). Vì vậy, tôi muốn coi đó là một x-ref tốt; Tôi không chắc chắn về bản sao, mặc dù. –

+2

Đề cử cho mở lại vì đây là về C, và khác là về C + +, hai ngôn ngữ hoàn toàn khác nhau. Cú pháp thực tế cũng rất khác nhau. –

Trả lời

18

Nếu một hàm gọi vô điều kiện một hàm _Noreturn, trình biên dịch sẽ có thể hiểu rằng:

  • mã sau đây là mã chết, cho phép tối ưu hóa (nó có thể được loại bỏ khỏi tạo ra nhị phân) và chẩn đoán - trình biên dịch sẽ có thể phát ra cảnh báo "mã không thể truy cập";
  • quan trọng nhất, biết rằng luồng bình thường từ chức năng bị gián đoạn nó sẽ có thể tránh cảnh báo giả mạo về giá trị trả về bị mất, biến chưa được khởi tạo và tương tự. Điều này đặc biệt quan trọng với các máy phân tích mã tĩnh - số lượng các kết quả sai được đưa ra bởi máy phân tích tĩnh CLang trong một ứng dụng lớn của chúng ta giảm đáng kể khi chúng tôi đánh dấu chức năng die của chúng tôi (đăng nhập một lỗi nghiêm trọng và chấm dứt ứng dụng) là noreturn.

Có thể có một số tối ưu hóa khác - vì hàm này không bao giờ trả về, không cần phải đẩy địa chỉ trả về trên ngăn xếp, lưu trạng thái đăng ký và bất cứ điều gì, tất cả những gì cần thiết là chuyển lập luận và thực hiện jmp để bắt đầu chức năng, mà không phải lo lắng về việc trả lại và dọn dẹp sau khi trả về. Nhưng tất nhiên, kể từ khi cuộc gọi là một-shot, hiệu suất để ép ở đây là chủ yếu là không đáng kể.

+0

bởi đối số này, ngay cả một hàm trả về có thể được đánh dấu là _Noreturn, đúng không ?? Ví dụ: 'int foo (dữ liệu * arg) {++ arg-> count; thanh trả về (arg); } '- function foo có thể được gọi với một bước nhảy và sau đó nhảy trở lại thanh() nơi dữ liệu thực sự được trả về. Hay tôi đã bỏ lỡ vấn đề? – user666412

+0

@ user666412: đó là tối ưu hóa cuộc gọi đuôi, chủ yếu là không liên quan.Áp dụng '_Noreturn' vào' bar' sẽ có nghĩa là nó * không bao giờ * trả về; OTOH, ở đây trình biên dịch chỉ có thể ủy quyền dọn dẹp thành 'bar' chỉ trong một trường hợp cụ thể. Ngoài ra, nhìn lại câu trả lời của tôi đặt quá nhiều sự nhấn mạnh vào khía cạnh tối ưu hóa (mà là biên cho các hàm '_noreturn', vì chúng rõ ràng hiếm khi được gọi), điểm chủ yếu là đánh dấu mã chết và điều chỉnh tốt hơn các cảnh báo trong môi trường xung quanh cuộc gọi (ví dụ: nếu tôi có một chức năng mà không 'thoát (1)' nó là không thích hợp nếu nó không trả lại hay không). –

+0

Nó vẫn có vẻ quá nhiều nỗ lực cho một cuộc gọi sẽ xảy ra nhiều nhất một lần trong một chương trình. – user666412

0

Nó cho phép tối ưu hóa bổ sung được thực hiện bởi trình biên dịch. Hãy xem here tại noreturn thuộc tính của GCC mà nó hỗ trợ cho một thời bây giờ (ngữ nghĩa có lẽ là giống nhau)

4

__attribute__((noreturn)) hoặc _Noreturn rất hữu ích cho các chức năng như die():

static __attribute__((noreturn)) void die(const char *fmt, ...) { 
    /* print a formatted error message and exit */ 
    exit(EXIT_FAILURE); 
} 
/* And let's say in main() you would want to exit because of an error but unforunately GCC complains about return value. */ 
int main() 
{ 
    if (!whatever) 
     die("a nasty error message goes here\n"); 
} 

Và cũng được sử dụng cho việc tối ưu như đã nêu.

+0

[JFYI] Bạn không cần phải rõ ràng "trả về" từ hàm main() (đây là dấu tích còn lại của tính tương thích C) – AlexT

+0

Nó chỉ là một ví dụ để chứng minh điều gì sẽ xảy ra. –

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