2014-12-19 7 views
6

Rozważmy następujący program:Czy gwarantowane UB może zostać odrzucone podczas kompilacji?

#include <stdio.h> 

int main(void) 
{ 
    int x; 
    while (1 == scanf("%d", &x)) 
     printf("%c\n", "hello"[x]); 
} 

Kompilator musi skompilować ten program z powodzeniem, ponieważ nie ma UB tak długo jak użytkownik nie wprowadzać żadnych numerów spoza zakresu 0 - 4.

Jednak zgodnie z this thread UB może cofnąć się w czasie. Rozważmy teraz ten program:

int main(void) 
{ 
    printf("hello\n"); 
    "hello"[6]; 
} 

Wszelkie wywołania tego programu powoduje zachowanie niezdefiniowane, a ponieważ, które mogą podróży w czasie, cała zachowanie tego programu na każdym wywołaniu jest niezdefiniowany. Czy zatem kompilator może odrzucić program i nie wygenerować pliku wykonywalnego? (Można powiedzieć, że UB cofa się w czasie do etapu kompilacji!)

+5

@Zaffy: '" cześć "[5]' to ''\ 0'',' "cześć" [6] 'jest poza związanym. – Jarod42

+0

@ Jarod42 oh, tak, przepraszam :) – Zaffy

+2

Niezawodne i dźwiękowe wykrywanie niezdefiniowanych zachowań jest problemem niemożliwym do rozwiązania lub nierozstrzygalnym .... –

Odpowiedz

13

Czy zatem kompilator może odrzucić program i nie wygenerować pliku wykonywalnego?

Tak. Definicja niezdefiniowanej zachowanie jest:

zachowanie, dla których niniejszy standard międzynarodowa nakłada żadnych wymagań [Uwaga: Niezdefiniowany zachowanie można oczekiwać, kiedy to Międzynarodowa Standardowa pomija żadnej wyraźnej definicji zachowań lub gdy program wykorzystuje błędne skonstruować lub błędne dane. Dopuszczalne nieokreślone zachowanie waha się od całkowitego zignorowania sytuacji z nieprzewidywalnymi wynikami, zachowania się podczas tłumaczenia lub wykonania programu w udokumentowany sposób, charakterystyczny dla środowiska (z wydaniem komunikatu diagnostycznego lub bez niego), do zakończenia tłumaczenia lub wykonania (z wydanie komunikatu diagnostycznego). Wiele błędnych konstrukcji programu nie powoduje niezdefiniowanych zachowań; są one wymagane do zdiagnozowania. - nota końcowa]

4

Aby dodać do odpowiedzi Jonathana.

Drugi program wywołuje niezdefiniowane zachowanie, a kompilator ma prawo zatrzymać tłumaczenie, ponieważ nieokreślone zachowanie nie jest ograniczone (c11, 3.4.3p1).

Pierwszy program może wywołać niezdefiniowane zachowanie, ale kompilator nie może zatrzymać tłumaczenia, ponieważ nie wszystkie ścieżki wykonania powodują niezdefiniowane zachowanie.

W Defect Report #109, C Komitet mówi:

Ponadto, jeżeli wszystkie możliwe wykonanie danego programu spowoduje zachowanie niezdefiniowane, dany program nie jest ściśle Conforming. Dopasowująca implementacja nie może nie przetłumaczyć ściśle zgodnego programu po prostu dlatego, że niektóre możliwe wykonanie tego programu spowodowałoby niezdefiniowane zachowanie.