2016-12-25 17 views
10

Người ta nói rằng vòng lặp vô hạn for(;;); là hành vi không xác định.Vòng lặp vô hạn vẫn chưa được xác định hành vi trong C++ nếu nó gọi thư viện được chia sẻ?


Từ http://en.cppreference.com/w/cpp/language/memory_model

Trong một chương trình hợp lệ C++, tất cả các chủ đề cuối cùng thực hiện một trong những sau:

  • chấm dứt
  • làm cho một cuộc gọi đến một I O thư viện/hàm
  • đọc hoặc sửa đổi đối tượng dễ bay hơi
  • thực hiện một hoạt động nguyên tử hoặc một hoạt động đồng bộ hóa

Không sợi thực hiện có thể thực hiện mãi mãi mà không thực hiện bất kỳ những hành vi quan sát được.

Lưu ý rằng nó có nghĩa là một chương trình với đệ quy vô tận hoặc vòng lặp vô hạn (cho dù được thực hiện dưới dạng tuyên bố hoặc theo vòng lặp hoặc nếu không) có hành vi không xác định.


Nhưng nếu nó gọi một hàm trong thư viện chia sẻ?

for(;;) sofunc();

Chức năng có thể làm bất kỳ loại blocking I/O, hoặc ném ngoại lệ.

Trong trường hợp này, trình biên dịch có giả định rằng vòng lặp có một số hành vi quan sát được không?

+2

nếu 'sofunc' không thực hiện một trong các thao tác được chỉ định, bạn có chương trình không hợp lệ. – Jarod42

+1

Tôi không biết bất kỳ trình biên dịch, hệ điều hành hoặc CPU nào gây ra bất kỳ sự cố nào bằng cách sử dụng vòng lặp kết thúc không trống hoặc vòng kết thúc không gọi hàm. ngoài thế giới chuẩn, câu hỏi này là vô lý. Tôi không có tuyên bố cho OP, tôi chỉ nghĩ rằng đây không phải là một vấn đề thực sự –

+0

Nhưng không phải là CALL một hướng dẫn nguyên tử? – Logman

Trả lời

3

Có một số nơi ngôn ngữ của tiêu chuẩn cung cấp cho các trình biên dịch tự do vượt quá những gì cần thiết để tối ưu hóa hữu ích, nhưng thay vào đó sẽ cung cấp trình biên dịch với các cách để ném Nguyên tắc tối thiểu ra ngoài cửa sổ. Cách thức các quy tắc về vòng lặp vô tận được viết phù hợp với loại đó.

Hầu hết các tối ưu hóa sẽ được tạo điều kiện bởi các quy tắc về vòng lặp vô tận sẽ được bật theo ngôn ngữ chỉ định rằng thời gian cần thiết để thực thi một đoạn mã, ngay cả khi vô hạn, không được coi là một bên- có hiệu lực mà trình biên dịch được yêu cầu để bảo tồn. Quy tắc như vậy sẽ cho phép trình biên dịch bỏ qua bất kỳ vòng lặp lặp nào không có bất kỳ tác dụng phụ trực tiếp nào và không sửa đổi các giá trị được sử dụng ở nơi khác.

Tiêu chuẩn, tuy nhiên, vượt xa điều đó. Với mã:

int foo(void) 
{ 
    int x=0; 
    do 
    { 
    x=functionWithNoSideEffects(x); 
    } while(x != 23 && x != 42); 
    return x; 
} 

một trình biên dịch mà có thể chứng minh rằng functionWithNoSideEffects sẽ không bao giờ có bất kỳ định nghĩa tác dụng phụ và sẽ không bao giờ quay trở lại 23 có thể thay thế mã cho "foo" với "return 42;". Ngay cả khi mục đích của chương trình là kiểm tra xem functionWithNoSideEffects có bao giờ trả về 42 hay không (nếu trường hợp có mã được sinh ra trả về 42 cho dù hàm đó có hay không sẽ không hữu ích), Standard sẽ không yêu cầu trình biên dịch tạo mã để thực sự kiểm tra trừ khi vòng lặp bao gồm một số loại "tác dụng phụ".

Tôi không tin rằng giá trị có quy tắc nói rằng nếu trình biên dịch có thể cho thấy vòng lặp không thể chấm dứt mà không X là đúng, chúng có thể coi X là đúng hay không. có nghĩa là nó có thể là . Tuy nhiên, tối ưu hóa dựa trên nguyên tắc đó có vẻ phổ biến.

+2

Tại sao '23'? Không phải là ['42'] (https://en.wikipedia.org/wiki/Life,_the_Universe_and_Everything)? – wallyk

+0

@wallyk: Tôi đã chỉnh sửa ví dụ để làm cho nó thú vị hơn một chút. Bạn có thích điều đó tốt hơn không? – supercat

+0

Chắc chắn là một sự cải tiến. Nhưng tôi nghĩ chỉ có * một * câu trả lời. – wallyk

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