Hướng dẫn sử dụng phần cứng bất hợp pháp


9

Trong khi điều tra một yêu cầu đáng ngờ , tôi đã viết chương trình thử nghiệm nhỏ nàynoway.c

int proveit()
{
    unsigned int n = 0;
    while (1) n++;
    return 0;
}

int main()
{
    proveit();
    return 0;
}

Kiểm tra cái này, tôi nhận được:

$ clang -O noway.c
$ ./a.out
zsh: illegal hardware instruction  ./a.out

Wat.

Nếu tôi biên dịch mà không tối ưu hóa, nó sẽ bị treo như mong đợi. Tôi nhìn vào hội đồng, và không có tiếng chuông và tiếng huýt sáo, mainchức năng trông như thế này:

_main:                                  ## @main
    pushq   %rbp
    movq    %rsp, %rbp
    ud2

Trong trường hợp ud2dường như là một hướng dẫn đặc biệt cho hành vi không xác định. Yêu cầu đáng ngờ đã nói ở trên, "Một chức năng không bao giờ trả lại là UB", được củng cố. Tôi vẫn thấy khó tin. Có thật không!? Bạn không thể viết một vòng lặp một cách an toàn?

Vì vậy, tôi đoán câu hỏi của tôi là:

  1. Đây có phải là một cách đọc đúng về những gì đang xảy ra?
  2. Nếu vậy, ai đó có thể chỉ cho tôi một số tài nguyên chính thức xác minh nó không?
  3. Tình huống mà bạn muốn loại tối ưu hóa này xảy ra là gì?

Thông tin liên quan

$ clang --version
Apple clang version 11.0.0 (clang-1100.0.20.17)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

3
IIRC, tràn int đã ký là UB.
wildplasser

1
int n = 0unsigned int n = 0;while (1);
^^ ^ ^ ^

1
Hmmm ... Trình biên dịch Explorer sẽ nhận được lệnh nhảy tự nhắm mục tiêu với -O gcc.godbolt.org/z/NTCQYT và bản dịch từng dòng mà không có nó. Có vẻ nhất quán trên nhiều phiên bản. Nhưng tôi cũng nhớ lại (mặc dù sẽ không tra cứu) rằng tiêu chuẩn C nói rằng việc không chấm dứt sẽ không có hiệu lực nếu nó không có tác dụng phụ . Dưới đây là Hans Boehm giải thích rằng điều này cho phép tối ưu hóa trình biên dịch nhất định không thể khác: open-std.org/jtc1/sc22/wg14/www/docs/n1528.htmlm
Gene

1
Hành vi không xác định được ký tràn số nguyên, không phải là vòng lặp vô hạn. Bạn có thể khắc phục bằng cách sử dụngunsigned int
MM

2
@Gene Tôi không nghĩ nó nói thế. Các vòng lặp không có phụ với các biểu thức kiểm soát không const có thể được coi là chấm dứt ( port70.net/~nsz/c/c11/n1570.html#6.8.5p6 ) nhưng vòng lặp bận sẽ ổn. UB nằm trong tràn số nguyên, mặc dù tôi không thể sao chép ví dụ bằng lệnh UD.
PSkocik

Câu trả lời:


3

Nếu bạn nhận được ud2 cho mã hiện có trong câu hỏi, thì trình biên dịch không phải là trình biên dịch C phù hợp. Bạn có thể báo cáo một lỗi biên dịch.

Lưu ý rằng trong C ++, mã này thực sự sẽ là UB. Khi các luồng được thêm vào (C11 và C ++ 11 tương ứng), đã có một đảm bảo tiến trình chuyển tiếp cho bất kỳ luồng nào, bao gồm luồng thực thi chính của chương trình không đa luồng.

Trong C ++, tất cả các luồng cuối cùng phải tiến triển, không có ngoại lệ. Tuy nhiên, trong C, một vòng lặp có biểu thức điều khiển là biểu thức không đổi không bắt buộc phải tiến triển. Tôi hiểu rằng C đã thêm ngoại lệ này vì nó đã được sử dụng phổ biến trong mã hóa nhúng để sử dụng một while(1) {}để treo chuỗi.

Câu hỏi tương tự với câu trả lời chi tiết hơn


Có tôi nhận được ud2từ mã C, nhưng cảm ơn bạn đã bao gồm thông tin về bảo đảm tiến trình chuyển tiếp C ++ (một thuật ngữ có vẻ như tôi sẽ có thể nghiên cứu), đó là điều tôi thực sự đã hỏi về nhưng được, tối ưu hóa đi như Tôi đã chuẩn bị câu hỏi.
luqui

Một cách tốt hơn về những gì tôi nghĩ rằng Ủy ban Tiêu chuẩn đã cố gắng nói là nếu trì hoãn mọi thứ trong một vòng lặp qua một hoạt động nhất định sẽ không ảnh hưởng đến hành vi chương trình, việc trì hoãn việc thực hiện vòng lặp như một quá khứ mà hoạt động đó sẽ không được coi là một hoạt động. thay đổi quan sát của hành vi.
supercat
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.