2013-08-07 9 views
7

Zauważyłem, że g++ skarżą się zbyt ściśle na temat crossed initialization i zastanawiam się, dlaczego te fałszywe pozytywne błędy nie mogą być usunięte tylko przez spojrzenie na formularz SSA programu podczas kompilacji.Przekroczenie "błąd inicjalizacji zmiennej" w C++?

Podam bardzo prosty przykład:

#include <cstdlib> 

int main() 
{ 
    goto end; 

    int i = 0; // unused variable declaration 

end: 
    return EXIT_SUCCESS; 
} 

Kiedy skompilowany z g++ -Wall -Wextra -o example1 example1.cc (g++ 4.8.1), kompilator daje następujący komunikat o błędzie:

example1.cc: In function ‘int main()’: 
example1.cc:10:2: error: jump to label ‘end’ [-fpermissive] 
    end: 
^
example1.cc:6:8: error: from here [-fpermissive] 
    goto end; 
     ^
example1.cc:8:7: error: crosses initialization of ‘int i’ 
    int i = 0; 
    ^
example1.cc:8:7: warning: unused variable ‘i’ [-Wunused-variable] 

Tak, to podniesie błąd, gdy w rzeczywistości nie ma ryzyka, ponieważ zmienna jest nieużywana (kompilator oczywiście ma obie informacje i nie może go połączyć, aby wydedukować, że błąd jest fałszywie dodatni).

Bardziej dziwne, miałem nadzieję, że LLVM był skuteczniejszy w analizie programu. Tak, próbowałem clang++ (LLVM) na tym prostym przykładzie z clang++ -Wall -Wextra -o example1 example1.cc (clang++ 3.4). I mam o tym samym komunikatem o błędzie:

example1.cc:8:7: warning: unused variable 'i' [-Wunused-variable] 
    int i = 0; 
    ^
example1.cc:6:3: error: goto into protected scope 
    goto end; 
^
example1.cc:8:7: note: jump bypasses variable initialization 
    int i = 0; 
    ^
1 warning and 1 error generated. 

Tak, jestem pewien, że jestem brakuje czegoś ważnego tutaj problem, który sprawia, że ​​wykrywanie tego fałszywie dodatni trudniejsze niż I chociaż. Ale nie wiem co to jest. A może specyfikacja C++ wyraźnie mówi, że tak musi być.

Jeśli ktoś ma pomysł, podziel się z nami!

Edit: Ja również skompilowany dokładnie ten sam kod w C (gcc lub clang), i poszło dobrze tylko z ostrzeżeniem o i będącego nieużywany zmienna. Wzmacnia to fakt, że jest to bardziej prawdopodobne, związane ze specyfikacją C++, a nie problemem wykrycia tego problemu w czasie kompilacji.

+0

nie Czy kod źle sformułowane niezależnie od tego, czy zmienna 'int I' jest używany, czy nie? Kompilatorzy narzekają na niezgodny kod, a nie na kod nie nadający się do kompilacji. – Walter

+1

Oba kompilatory wykonują dokładnie to, co zaleca standard. Przekraczanie inicjalizacji jest niedozwolone, kropka, koniec historii. Nie ma nic do analizy. –

+0

OK, tego właśnie przegapiłem. Wynika to głównie ze specyfikacji języka C++, a nie z powodu problemu technicznego. – perror

Odpowiedz

10

Nie ma nic złego w kompilatorach. Twój kod jest źle sformułowany zgodnie ze standardem.

W tym konkretnym przypadku wymóg normy może nie być konieczny, a skok może być dozwolony, a kompilator może utworzyć poprawny kod. Jednakże dzieje się tak tylko dlatego, że inicjalizacja zmiennej int i nie ma skutków ubocznych.

Można uczynić Twój kod ważny po prostu załączając wskoczył sekcję we własnym zakresie:

#include <cstdlib> 

int main() 
{ 
    goto end; 
    { 
    int i = 0; // unused variable declaration 
    } 
end: 
    // cannot use i here, as it's not defined. 
    return EXIT_SUCCESS; 
} 
+0

Gdzie w specyfikacji jest napisane? Nie mogę tego znaleźć... – perror

8

Jest to niedozwolone, ponieważ potencjalnie można wywołać destruktory dla obiektów, które nie są poprawnie skonstruowane. Wprawdzie, int nie ma konstruktora ani destruktora, ale czyni go "fair" dla wszystkich typów obiektów. Z technicznego punktu widzenia, coś na etykiecie end: może być używane jako i, a dzięki regule ścisłej uniemożliwia maszynie sprawdzanie każdej ścieżki kodowej (która staje się "problemem zatrzymania").

Powiązane problemy