2013-08-07 57 views
7

Tôi nhận thấy rằng g++ phàn nàn một chút quá nghiêm ngặt về crossed initialization và tôi tự hỏi tại sao các lỗi dương tính giả này không thể bị xóa chỉ bằng cách xem biểu mẫu SSA của chương trình trong khi biên dịch.Ghi đè lỗi "chuyển khởi tạo biến" trong C++?

Để tôi cho một ví dụ rất đơn giản:

#include <cstdlib> 

int main() 
{ 
    goto end; 

    int i = 0; // unused variable declaration 

end: 
    return EXIT_SUCCESS; 
} 

Khi biên soạn với g++ -Wall -Wextra -o example1 example1.cc (g++ 4.8.1), trình biên dịch cung cấp cho các thông báo lỗi sau:

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] 

Vì vậy, nó sẽ nâng cao một lỗi mà thực sự không có rủi ro vì biến này không được sử dụng (trình biên dịch rõ ràng có cả thông tin và không thể kết hợp nó để suy ra rằng lỗi là dương tính giả).

Kỳ lạ hơn, tôi hy vọng rằng LLVM hiệu quả hơn trong việc phân tích chương trình. Vì vậy, tôi đã thử clang++ (LLVM) trên ví dụ đơn giản này với clang++ -Wall -Wextra -o example1 example1.cc (clang++ 3.4). Và, tôi nhận được thông báo lỗi tương tự:

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. 

Vì vậy, tôi khá chắc chắn rằng tôi thiếu điều gì đó quan trọng ở đây, một vấn đề khiến cho việc phát hiện này dương tính khó hơn tôi. Nhưng, tôi không biết nó là gì. Hoặc có thể, đặc tả C++ đặc biệt nói rằng nó phải như thế này.

Nếu ai đó có ý tưởng, hãy chia sẻ!

Sửa: Tôi cũng biên soạn mã chính xác tương tự trong C (gcc hoặc clang), và nó diễn ra tốt đẹp chỉ với cảnh báo về i là một biến không sử dụng. Vì vậy, nó củng cố một thực tế rằng điều này có nhiều khả năng liên kết với các đặc điểm kỹ thuật của C + + và không phải là một vấn đề phát hiện vấn đề này tại thời gian biên dịch.

+0

Không phải là mã vô hình thành bất kể biến 'int i' được sử dụng hay không? Các trình biên dịch phàn nàn về mã không phù hợp, không phải về mã không biên dịch được. – Walter

+1

Cả hai trình biên dịch đều làm chính xác những gì tiêu chuẩn quy định. Vượt qua một khởi tạo không được phép, toàn dừng lại, kết thúc của câu chuyện. Không có gì để phân tích. –

+0

Ok, đây là những gì tôi đã bỏ lỡ. Điều này chủ yếu đến từ đặc điểm kỹ thuật của C++ và không phải vì có một vấn đề kỹ thuật tiềm ẩn. – perror

Trả lời

10

Không có gì sai với trình biên dịch. Mã của bạn không đúng định dạng theo tiêu chuẩn.

Trong trường hợp cụ thể của bạn, yêu cầu của tiêu chuẩn có thể không cần thiết và có thể cho phép nhảy và trình biên dịch có thể tạo mã hợp lệ. Tuy nhiên, điều này chỉ vì việc khởi tạo biến số int i không có tác dụng phụ.

Bạn có thể làm cho mã của bạn hợp lệ bằng cách đơn giản kèm theo phần nhảy trong phạm vi riêng của mình:

#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

Địa chỉ trong thông số được nêu ở đâu? Tôi không thể tìm thấy nó... – perror

8

Điều này không được phép vì có khả năng bạn sẽ gọi destructors cho các đối tượng không được xây dựng đúng cách. Phải thừa nhận rằng, int không có hàm tạo hoặc hàm hủy, nhưng nó làm cho nó "công bằng" cho tất cả các loại đối tượng. Và về mặt kỹ thuật, một cái gì đó ở nhãn end: có thể đang sử dụng i và bằng cách làm cho quy tắc nghiêm ngặt, nó ngăn máy phải kiểm tra từng đường dẫn mã đơn (trở thành "sự cố tạm dừng").

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