2012-12-03 11 views
13

Powiel możliwe:
What is the point of the Noreturn attribute?Zastosowanie _Noreturn w C11

C11 wprowadzono atrybut _Noreturn, aby wskazać, że funkcja nie zwraca.

Z wyjątkiem wartości dokumentacji w kodzie źródłowym, jakie inne korzyści zapewnia atrybut i dlaczego należy go użyć?

+1

http://stackoverflow.com/questions/10538291/what-is-the-point-of-the-noreturn-attribute zadaje to samo pytanie w języku C++. Rozumowanie C jest dokładnie takie samo. –

+3

Rozumowanie jest podobne; składnia wydaje się być całkowicie różna między C++ ('[[noreturn]]') i C ('_Noreturn' lub' noreturn', jeśli zawarłeś ''). Tak więc uważam to za dobry x-ref; Nie jestem jednak pewien co do duplikacji. –

+2

Nominuj do ponownego otwarcia, ponieważ dotyczy to C, a drugi dotyczy C++, dwóch zupełnie różnych języków. Rzeczywista składnia również jest bardzo różna. –

Odpowiedz

18

Jeśli funkcja zwraca bezwarunkowo _Noreturn funkcji, kompilator będzie mógł zrozumieć, że:

  • kod, który następuje, jest martwy kod, który pozwala na optymalizację (można go usunąć z wygenerowany binarny) i diagnostyka - kompilator będzie mógł emitować ostrzeżenia "nieosiągalny kod";
  • co najważniejsze, wiedząc, że normalny przepływ z funkcji zostanie przerwany, będzie mógł uniknąć fałszywych ostrzeżeń o brakujących wartościach zwracanych, niezainicjowanych zmiennych i tym podobnych.

    Jest to szczególnie ważne ze statycznych analizatorów kodowych - liczba fałszywych alarmów podanych przez dzyń statycznych analizatora w biggish stosowania naszych spadła znacznie raz obchodziliśmy nasze die funkcja (log błąd krytyczny i zamknąć aplikację) jako noreturn.

Nie mogą być również niektóre inne optymalizację dostępnych - ponieważ funkcja nigdy nie powróci, nie ma potrzeby naciskać na adres zwrotny na stosie, zapisz stan rejestrów i cokolwiek, wszystko, co jest potrzebne, aby przekazać argumenty i wykonaj jmp na początku funkcji, nie martwiąc się o powrót i oczyszczanie po zwrocie. Ale oczywiście, ponieważ połączenie jest jednorazowe, występ, który można tu wycisnąć, jest w większości znikomy.

+0

tym argumentem, nawet funkcja, która zwraca, może być oznaczona jako _Noreturn, prawda? Przykład: 'int foo (dane * arg) {++ arg-> count; pasek powrotu (arg); } '- funkcja foo może zostać wywołana za pomocą skoku, a następnie przeskoczyć ponownie do baru(), gdzie dane są faktycznie zwracane. A może przegapiłem ten punkt? – user666412

+0

@ user666412: to jest optymalizacja połączeń, która jest w większości niezwiązana.Użycie '_NORUMENT' do' bar' oznaczałoby, że * nigdy * zwraca; OTOH, tutaj kompilator może po prostu przekazać porządek do 'bar' w tylko jednej konkretnej instancji. Również z perspektywy czasu moja odpowiedź kładzie zbyt duży nacisk na aspekt optymalizacji (który jest marginalny dla funkcji '_noreturn', ponieważ są one oczywiście rzadko nazywane), chodzi głównie o zaznaczenie martwego kodu i lepsze dostosowanie ostrzeżeń w otoczeniu takich znaków. wywołania (np. jeśli mam funkcję, która wykonuje polecenie "exit (1)", nie ma znaczenia, czy zwraca wartość, czy nie). –

+0

Nadal wydaje się zbyt wiele wysiłku, aby zadzwonić, co nastąpi najwyżej raz w programie. – user666412

0

Pozwala to na dodatkowe kompilacje optymalizacji. Spójrz here w atrybucie GCC noreturn który obsługuje na chwilę teraz (semantyka jest prawdopodobnie taka sama)

4

__attribute__((noreturn)) lub _Noreturn jest przydatna dla funkcji jak 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"); 
} 

a także jest wykorzystywany do optymalizacji jak stwierdził.

+0

[JFYI] Nie trzeba jawnie "zwracać" z funkcji main() (to jest pozostałość kompatybilności z C). – AlexT

+0

To był tylko przykład, aby zademonstrować, co się stanie. –