“ คำสั่งฮาร์ดแวร์ที่ผิดกฎหมาย” จากรหัสที่ง่ายมาก


9

ในขณะที่ตรวจสอบการอ้างสิทธิ์ที่น่าสงสัยฉันได้เขียนโปรแกรมทดสอบเล็กน้อยนี้noway.c

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

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

ทดสอบสิ่งนี้ฉันจะได้รับ:

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

วัด

หากฉันรวบรวมโดยไม่มีการเพิ่มประสิทธิภาพมันแฮงค์ตามที่คาดไว้ ฉันดูที่ชุมนุมและไม่มีเสียงระฆังและเสียงนกหวีดmainฟังก์ชั่นที่มีลักษณะเช่นนี้:

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

ที่ud2เห็นได้ชัดคือคำสั่งที่เฉพาะเจาะจงสำหรับพฤติกรรมที่ไม่ได้กำหนด การเรียกร้องที่น่าสงสัยดังกล่าว "ฟังก์ชั่นที่ไม่เคยส่งคืนคือ UB" ได้รับการเสริม ฉันยังคงพบว่ามันยากที่จะเชื่อ จริงๆ!? คุณไม่สามารถเขียนวนรอบสปินได้อย่างปลอดภัยหรือไม่?

ดังนั้นฉันเดาคำถามของฉัน:

  1. นี่เป็นการอ่านที่ถูกต้องของสิ่งที่เกิดขึ้นหรือไม่?
  2. ถ้าเป็นเช่นนั้นใครบางคนสามารถชี้ให้ฉันไปที่แหล่งข้อมูลอย่างเป็นทางการที่ตรวจสอบได้?
  3. สถานการณ์ใดที่คุณต้องการให้การเพิ่มประสิทธิภาพประเภทนี้เกิดขึ้น

ข้อมูลที่เกี่ยวข้อง

$ 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 การโอเวอร์โฟลว์ int ที่ลงนามแล้วคือ UB
wildplasser

1
^^^^ ie int n = 0===> unsigned int n = 0;หรือยังดีกว่า ..while (1);
WhozCraig

1
อืม ... คอมไพเลอร์ Explorer ดังสนั่นได้รับคำสั่งการกระโดดด้วยตนเองเป้าหมายด้วย -O gcc.godbolt.org/z/NTCQYTและการแปลแบบบรรทัดต่อบรรทัดโดยไม่มีมัน ดูเหมือนจะสอดคล้องกันในหลาย ๆ รุ่น แต่ฉันยังจำได้ (แม้ว่าจะไม่มองมันได้) ที่มาตรฐานซีกล่าวว่าการเลิกจ้างที่ไม่เป็น UB ถ้ามันเป็นผลข้างเคียงฟรี นี่คือ Hans Boehm อธิบายว่าสิ่งนี้ช่วยให้การเพิ่มประสิทธิภาพคอมไพเลอร์เป็นไปไม่ได้: open-std.org/jtc1/sc22/wg14/www/docs/n1528.htm
Gene

1
พฤติกรรมที่ไม่ได้กำหนดนั้นเป็นจำนวนเต็มล้นไม่ใช่แบบวนอนันต์ คุณสามารถแก้ไขได้โดยใช้unsigned int
MM

2
@ ยีนฉันไม่คิดว่ามันจะบอกว่า ลูปที่ปราศจากสิ่งข้างเคียงที่มีนิพจน์การควบคุมที่ไม่ใช่ const อาจถูกสมมติให้ยุติ ( port70.net/~nsz/c/c11/n1570.html#6.8.5p6 ) แต่การวนลูปที่ยุ่งควรจะดี UB อยู่ในจำนวนเต็มล้น แต่ฉันไม่สามารถทำซ้ำตัวอย่างด้วยคำสั่ง UD
PSkocik

คำตอบ:


3

หากคุณได้รับ ud2 สำหรับรหัสที่ตอนนี้มีคำถามแล้วคอมไพเลอร์ไม่ได้เป็นคอมไพเลอร์ C ที่สอดคล้องกัน คุณสามารถรายงานข้อผิดพลาดของคอมไพเลอร์

โปรดทราบว่าใน C ++ รหัสนี้จะเป็น UB จริง ๆ เมื่อมีการเพิ่มเธรด (C11 และ C ++ 11 ตามลำดับ) จะมีการรับประกันความคืบหน้าล่วงหน้าสำหรับเธรดใด ๆ รวมถึงเธรดการเรียกใช้งานหลักของโปรแกรมที่ไม่ใช่มัลติเธรด

ใน C ++ กระทู้ทั้งหมดจะต้องดำเนินการในที่สุดโดยไม่มีข้อยกเว้น อย่างไรก็ตามใน C หมายถึงลูปที่มีนิพจน์ควบคุมเป็นนิพจน์คงที่ไม่จำเป็นต้องดำเนินการ ความเข้าใจของฉันคือ C เพิ่มข้อยกเว้นนี้เพราะมันเป็นเรื่องธรรมดาในการเข้ารหัสแบบฝังเพื่อใช้ในwhile(1) {}การแขวนเธรด

คำถามที่คล้ายกันพร้อมคำตอบโดยละเอียดเพิ่มเติม


ใช่ฉันจะได้รับud2จากรหัส C แต่ขอขอบคุณสำหรับการรวมข้อมูลเกี่ยวกับการรับประกันความคืบหน้าของ C ++ (คำที่ดูเหมือนว่าฉันจะสามารถค้นคว้าได้) ซึ่งเป็นสิ่งที่ฉันถามจริง ๆ แต่ได้รับการปรับให้เหมาะสม ฉันกำลังเตรียมคำถาม
luqui

การกล่าวถ้อยคำที่ดีขึ้นเกี่ยวกับสิ่งที่ฉันคิดว่าคณะกรรมการมาตรฐานพยายามพูดคือหากการเลื่อนทุกสิ่งภายในลูปที่ผ่านมาการดำเนินการบางอย่างจะไม่ส่งผลกระทบต่อพฤติกรรมของโปรแกรมอย่างเห็นได้ชัด การเปลี่ยนแปลงพฤติกรรมที่สังเกตได้
supercat
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.