คำถามติดแท็ก undefined-behavior

ผลลัพธ์ที่คาดเดาไม่ได้ของการคอมไพล์หรือเอ็กซีคิ้วท์โปรแกรมที่ทำลายกฏของภาษาไม่ว่าจะเป็นคอมไพเลอร์, ล่ามหรือระบบรันไทม์จะต้องบังคับใช้ ห้ามใช้แท็กนี้สำหรับคำถามเกี่ยวกับประเภทข้อมูลหรือค่าส่งคืนของ "undefined" ในกรณีเหล่านั้นควรใช้แท็ก [ไม่ได้กำหนด] แทน

5
พฤติกรรมที่ไม่ได้กำหนดและจุดลำดับ
"คะแนนตามลำดับ" คืออะไร? ความสัมพันธ์ระหว่างพฤติกรรมที่ไม่ได้กำหนดและคะแนนตามลำดับคืออะไร? ฉันมักจะใช้การแสดงออกที่ตลกและซับซ้อนเช่นa[++i] = i;ทำให้ฉันรู้สึกดีขึ้น เหตุใดฉันจึงควรหยุดใช้งาน หากคุณได้อ่านบทความนี้ให้แน่ใจว่าจะแวะไปที่ติดตามคำถามไม่ได้กำหนดพฤติกรรมและลำดับจุดโหลดใหม่ (หมายเหตุ: นี่คือหมายถึงการเป็นรายการที่จะกองมากเกินของ C ++ คำถามที่พบบ่อย . ถ้าคุณต้องการที่จะวิจารณ์ความคิดของการให้คำถามที่พบบ่อยในรูปแบบนี้แล้วโพสต์บนเมตาที่เริ่มต้นทั้งหมดนี้ . จะเป็นสถานที่ที่จะทำเช่นนั้นได้คำตอบ คำถามนั้นได้รับการตรวจสอบในห้องสนทนา C ++ซึ่งแนวคิด FAQ เริ่มต้นตั้งแต่แรกดังนั้นคำตอบของคุณมีโอกาสมากที่จะได้รับการอ่านโดยผู้ที่คิดแนวคิดนี้)

14
ทำไมโครงสร้างเหล่านี้โดยใช้พฤติกรรมที่ไม่ได้กำหนดไว้ล่วงหน้าและหลังเพิ่มขึ้น?
#include <stdio.h> int main(void) { int i = 0; i = i++ + ++i; printf("%d\n", i); // 3 i = 1; i = (i++); printf("%d\n", i); // 2 Should be 1, no ? volatile int u = 0; u = u++ + ++u; printf("%d\n", u); // 1 u = 1; …


8
พฤติกรรมที่ไม่ได้กำหนดไม่ระบุและไม่ได้กำหนดและการนำไปปฏิบัติ
พฤติกรรมที่ไม่ได้กำหนดใน C และ C ++ คืออะไร สิ่งที่เกี่ยวกับพฤติกรรมที่ไม่ระบุและพฤติกรรมที่กำหนดไว้ในการนำไปใช้ ความแตกต่างระหว่างพวกเขาคืออะไร?

5
มาตรฐาน C ++ อนุญาตให้บูลที่ไม่กำหนดค่าเริ่มต้นขัดข้องโปรแกรมหรือไม่
ฉันรู้ว่า"พฤติกรรมที่ไม่ได้กำหนด"ใน C ++ สามารถอนุญาตให้คอมไพเลอร์ทำสิ่งที่ต้องการได้ อย่างไรก็ตามฉันมีข้อผิดพลาดที่ทำให้ฉันประหลาดใจเพราะฉันคิดว่ารหัสนั้นปลอดภัยพอ ในกรณีนี้ปัญหาจริงเกิดขึ้นเฉพาะแพลตฟอร์มที่ใช้คอมไพเลอร์เฉพาะและเฉพาะในกรณีที่เปิดใช้งานการเพิ่มประสิทธิภาพ ฉันลองหลายสิ่งหลายอย่างเพื่อทำให้เกิดปัญหาอีกครั้งและทำให้มันง่ายขึ้นสูงสุด นี่คือการแยกฟังก์ชั่นที่เรียกSerializeว่าจะใช้พารามิเตอร์บูลและคัดลอกสตริงtrueหรือfalseไปยังบัฟเฟอร์ปลายทางที่มีอยู่ ฟังก์ชั่นนี้จะอยู่ในการตรวจสอบรหัสหรือไม่ไม่มีทางที่จะบอกได้ว่าในความเป็นจริงอาจมีปัญหาหากพารามิเตอร์ bool เป็นค่าเริ่มต้นหรือไม่ // Zero-filled global buffer of 16 characters char destBuffer[16]; void Serialize(bool boolValue) { // Determine which string to print based on boolValue const char* whichString = boolValue ? "true" : "false"; // Compute the length of the string we …

22
ตัวแปรโลคัลแบบไม่กำหนดค่าเริ่มต้นเป็นตัวสร้างตัวเลขสุ่มที่เร็วที่สุดหรือไม่
ฉันรู้ว่าตัวแปรท้องถิ่นที่ไม่ได้กำหนดค่าเริ่มต้นคือพฤติกรรมที่ไม่ได้กำหนด ( UB ) และค่าอาจมีการแทนแทร็บซึ่งอาจส่งผลต่อการดำเนินการต่อไป แต่บางครั้งฉันต้องการใช้ตัวเลขสุ่มเท่านั้นสำหรับการแสดงด้วยภาพ โปรแกรมตัวอย่างเช่นตั้งค่าบางสิ่งที่มีสีแบบสุ่มในเอฟเฟ็กต์ภาพเช่น: void updateEffect(){ for(int i=0;i<1000;i++){ int r; int g; int b; star[i].setColor(r%255,g%255,b%255); bool isVisible; star[i].setVisible(isVisible); } } มันเร็วกว่าไหม void updateEffect(){ for(int i=0;i<1000;i++){ star[i].setColor(rand()%255,rand()%255,rand()%255); star[i].setVisible(rand()%2==0?true:false); } } และยังเร็วกว่าตัวสร้างตัวเลขสุ่มอื่น ๆ

11
ทำไม f (i = -1, i = -1) พฤติกรรมที่ไม่ได้กำหนด?
ฉันกำลังอ่านเกี่ยวกับลำดับของการละเมิดการประเมินผลและพวกเขายกตัวอย่างที่ทำให้ฉันสงสัย 1) หากผลข้างเคียงของวัตถุสเกลาร์นั้นไม่ได้ถูกจัดลำดับสัมพันธ์กับผลข้างเคียงอื่นในวัตถุสเกลาร์เดียวกันพฤติกรรมนั้นจะไม่ได้กำหนดไว้ // snip f(i = -1, i = -1); // undefined behavior ในบริบทiนี้เป็นวัตถุสเกลาร์ซึ่งเห็นได้ชัดว่าหมายถึง ประเภทเลขคณิต (3.9.1), ประเภทการแจงนับ, ประเภทตัวชี้, ตัวชี้ไปยังประเภทสมาชิก (3.9.2), std :: nullptr_t, และเวอร์ชันที่ผ่านการรับรอง cv ของประเภทเหล่านี้ (3.9.3) เรียกว่าประเภทสเกลาร์ ฉันไม่เห็นว่าคำสั่งนั้นคลุมเครือในกรณีนั้นอย่างไร สำหรับฉันดูเหมือนว่าไม่ว่าอาร์กิวเมนต์แรกหรืออาร์กิวเมนต์ที่สองจะได้รับการประเมินก่อนiจะสิ้นสุดลง-1และอาร์กิวเมนต์ทั้งสองก็เช่น-1กัน บางคนช่วยอธิบายได้ไหม? UPDATE ฉันขอขอบคุณการอภิปรายทั้งหมด ถึงตอนนี้ฉันชอบคำตอบของ @ harmicมากเพราะมันทำให้เกิดข้อผิดพลาดและความซับซ้อนของการกำหนดคำสั่งนี้แม้จะมองไปข้างหน้าอย่างรวดเร็วในทันที @ acheong87ชี้ให้เห็นปัญหาบางอย่างที่เกิดขึ้นเมื่อใช้การอ้างอิง แต่ฉันคิดว่ามันเป็นมุมฉากกับผลข้างเคียงที่ตามมาของคำถามนี้ สรุป เนื่องจากคำถามนี้ได้รับความสนใจเป็นจำนวนมากฉันจะสรุปประเด็น / คำตอบหลัก ๆ ก่อนอื่นให้ฉันพูดนอกเรื่องเล็ก ๆ เพื่อชี้ให้เห็นว่า "ทำไม" สามารถมีความหมายที่แตกต่างกันอย่างใกล้ชิด …

14
เหตุใดจึงเป็นเช่นนี้สำหรับการออกจากลูปในบางแพลตฟอร์มและไม่ใช่ในแพลตฟอร์มอื่น
ฉันเพิ่งเริ่มเรียนรู้ C และฉันกำลังเรียนกับ C เป็นหัวเรื่อง ฉันกำลังเล่นกับลูปและฉันพบกับพฤติกรรมแปลก ๆ ซึ่งฉันไม่รู้จะอธิบายอย่างไร #include <stdio.h> int main() { int array[10],i; for (i = 0; i <=10 ; i++) { array[i]=0; /*code should never terminate*/ printf("test \n"); } printf("%d \n", sizeof(array)/sizeof(int)); return 0; } ในแล็ปท็อปที่ใช้ Ubuntu 14.04 รหัสนี้จะไม่หยุด มันจะเสร็จสมบูรณ์ บนคอมพิวเตอร์ของโรงเรียนที่ใช้ CentOS 6.6 มันก็ทำงานได้ดี บน Windows 8.1 …

5
เหตุใดพฤติกรรมที่กำหนดไว้ล้นของจำนวนเต็มล้นที่ไม่ได้ลงนาม แต่ล้นจำนวนเต็มที่ลงนามไม่ได้
จำนวนเต็มมากเกินที่ไม่ได้ลงนามนั้นถูกกำหนดไว้อย่างดีทั้งในมาตรฐาน C และ C ++ ตัวอย่างเช่นมาตรฐาน C99 ( §6.2.5/9) การคำนวณที่เกี่ยวข้องกับตัวถูกดำเนินการที่ไม่ได้ลงนามไม่สามารถเกิน fl ow ได้เนื่องจากผลลัพธ์ที่ไม่สามารถแสดงได้ด้วยประเภทจำนวนเต็มที่ไม่ได้ลงนามผลจะลดลงแบบโมดูโลจำนวนที่มากกว่าหนึ่งค่าที่ใหญ่ที่สุดที่สามารถแสดงด้วยประเภทผลลัพธ์ อย่างไรก็ตามทั้งสองมาตรฐานระบุว่าการโอเวอร์โฟลว์จำนวนเต็มที่ลงนามนั้นเป็นพฤติกรรมที่ไม่ได้กำหนด อีกครั้งจากมาตรฐาน C99 ( §3.4.3/1) ตัวอย่างของพฤติกรรมที่ไม่ได้แก้ไขคือพฤติกรรมของจำนวนเต็มส่วนเกิน มีประวัติศาสตร์หรือ (ดีกว่า!) เหตุผลทางเทคนิคสำหรับความคลาดเคลื่อนนี้หรือไม่?

11
พฤติกรรมที่ไม่ได้กำหนดทั่วไปทั้งหมดที่โปรแกรมเมอร์ C ++ ควรรู้คืออะไร [ปิด]
เป็นการยากที่จะบอกสิ่งที่ถูกถามที่นี่ คำถามนี้คลุมเครือคลุมเครือไม่สมบูรณ์กว้างเกินไปหรือโวหารและไม่สามารถตอบได้อย่างสมเหตุสมผลในรูปแบบปัจจุบัน สำหรับความช่วยเหลือในการทำความเข้าใจคำถามนี้เพื่อที่จะสามารถเปิด, ไปที่ศูนย์ช่วยเหลือ ปิดให้บริการใน7 ปีที่ผ่านมา ล็อคแล้ว คำถามและคำตอบของคำถามนี้ถูกล็อคเนื่องจากคำถามอยู่นอกหัวข้อ แต่มีความสำคัญทางประวัติศาสตร์ ขณะนี้ไม่ยอมรับคำตอบหรือการโต้ตอบใหม่ พฤติกรรมที่ไม่ได้กำหนดทั่วไปทั้งหมดที่โปรแกรมเมอร์ C ++ ควรรู้คืออะไร พูดเช่น: a[i] = i++;

15
ในทางปฏิบัติทำไมคอมไพเลอร์ที่ต่างกันจึงคำนวณค่า int x = ++ i + ++ i ต่างกัน?
พิจารณารหัสนี้: int i = 1; int x = ++i + ++i; เรามีการคาดเดาว่าคอมไพเลอร์อาจทำอะไรกับโค้ดนี้โดยสมมติว่าคอมไพเลอร์ ทั้ง++iผลตอบแทนที่เกิดใน2x=4 หนึ่งใน++iผลตอบแทน2และผลตอบแทนอื่น ๆ ที่มีผลในการ3x=5 ทั้ง++iผลตอบแทนที่เกิดใน3x=6 สำหรับฉันอย่างที่สองดูเหมือนจะเป็นไปได้มากที่สุด หนึ่งในสอง++ตัวดำเนินการถูกดำเนินการด้วยi = 1ค่าที่iเพิ่มขึ้นและผลลัพธ์2จะถูกส่งกลับ จากนั้นตัว++ดำเนินการที่สองจะถูกดำเนินการด้วยi = 2ค่าที่iเพิ่มขึ้นและผลลัพธ์3จะถูกส่งกลับ แล้ว2และมีการเพิ่มเข้าด้วยกันเพื่อให้35 แต่ผมวิ่งรหัสนี้ใน Visual Studio 6และผลที่ได้ก็คือ ฉันพยายามทำความเข้าใจคอมไพเลอร์ให้ดีขึ้นและฉันสงสัยว่าอะไรอาจนำไปสู่ผลลัพธ์ของ6ไฟล์. ฉันเดาเพียงอย่างเดียวคือโค้ดสามารถทำงานพร้อมกัน "ในตัว" บางอย่างได้ สอง++ผู้ประกอบการถูกเรียกว่าแต่ละคนเพิ่มขึ้นก่อนที่จะกลับมาอีกแล้วพวกเขาทั้งสองกลับi 3สิ่งนี้จะขัดแย้งกับความเข้าใจของฉันเกี่ยวกับ call stack และจำเป็นต้องอธิบายออกไป สิ่งใด (ที่สมเหตุสมผล) ที่C++คอมไพเลอร์สามารถทำได้ซึ่งจะนำไปสู่ผลลัพธ์4หรือผลลัพธ์หรือ6? บันทึก ตัวอย่างนี้เป็นตัวอย่างของพฤติกรรมที่ไม่ได้กำหนดไว้ในการเขียนโปรแกรมของ Bjarne Stroustrup: หลักการและการปฏิบัติโดยใช้ C ++ (C ++ …

5
ทำไมลูปนี้สร้าง“ คำเตือน: การวนซ้ำ 3u เรียกใช้พฤติกรรมที่ไม่ได้กำหนด” และส่งออกมากกว่า 4 บรรทัด
รวบรวมสิ่งนี้: #include <iostream> int main() { for (int i = 0; i < 4; ++i) std::cout << i*1000000000 << std::endl; } และgccสร้างคำเตือนต่อไปนี้: warning: iteration 3u invokes undefined behavior [-Waggressive-loop-optimizations] std::cout << i*1000000000 << std::endl; ^ ฉันเข้าใจว่ามีจำนวนเต็มล้นที่ลงนามแล้ว สิ่งที่ฉันไม่สามารถทำได้คือทำไม iค่าจึงแตกโดยการดำเนินการมากเกินไป ฉันได้อ่านคำตอบว่าทำไมจำนวนเต็มล้นใน x86 กับ GCC ทำให้เกิดการวนซ้ำไม่สิ้นสุด? แต่ฉันยังไม่ชัดเจนว่าทำไมสิ่งนี้เกิดขึ้น - ฉันได้รับ "undefined" หมายถึง "อะไรก็ได้ที่เกิดขึ้น" แต่สาเหตุพื้นฐานของพฤติกรรมที่เฉพาะเจาะจงนี้คืออะไร …

8
ปรับแต่ง“ ในขณะที่ (1);” ใน C ++ 0x
อัปเดตดูด้านล่าง! ฉันเคยได้ยินและอ่านว่า C ++ 0x อนุญาตให้คอมไพเลอร์พิมพ์ "Hello" สำหรับตัวอย่างต่อไปนี้ #include <iostream> int main() { while(1) ; std::cout << "Hello" << std::endl; } เห็นได้ชัดว่ามีบางอย่างเกี่ยวข้องกับเธรดและความสามารถในการปรับให้เหมาะสม ฉันคิดว่ามันน่าแปลกใจที่หลาย ๆ คนคิดว่า บางคนมีคำอธิบายที่ดีว่าเหตุใดจึงจำเป็นต้องอนุญาต สำหรับการอ้างอิง C ++ 0x ฉบับร่างล่าสุดระบุไว้ที่6.5/5 ลูปที่นอกเหนือจากคำสั่ง for-init ในกรณีของคำสั่ง for ไม่เรียกใช้ฟังก์ชันห้องสมุด I / O และ ไม่สามารถเข้าถึงหรือแก้ไขวัตถุที่ระเหยได้และ ไม่มีการดำเนินการซิงโครไนซ์ (1.10) หรือการดำเนินการปรมาณู (ข้อ 29) อาจถูกสันนิษฐานโดยการนำไปปฏิบัติเพื่อยุติ [หมายเหตุ: สิ่งนี้มีจุดประสงค์เพื่อให้การแปลงคอมไพเลอร์เช่นการลบลูปที่ว่างเปล่าแม้ว่าจะไม่สามารถพิสูจน์ได้ว่าการเลิกจ้าง - …

5
เหตุใดเครื่องมือเพิ่มประสิทธิภาพ GCC 6 ที่ปรับปรุงแล้วจึงใช้งาน C ++ ได้จริง
GCC 6 มีคุณลักษณะเครื่องมือเพิ่มประสิทธิภาพใหม่ : จะถือว่าthisไม่เป็นโมฆะและปรับให้เหมาะสมตามนั้น ตอนนี้การแพร่กระจายช่วงค่าถือว่าตัวชี้ของฟังก์ชันสมาชิก C ++ นี้ไม่ใช่ค่าว่าง กำจัดนี้ null ร่วมกันตรวจสอบตัวชี้แต่ยังแบ่งบางส่วนไม่สอดคล้องรหัสฐาน (เช่น Qt-5, โครเมี่ยม, KDevelop) สามารถใช้การแก้ไขชั่วคราว -fno-delete-null-pointer-checks ชั่วคราวได้ รหัสที่ไม่ถูกต้องสามารถระบุได้โดยใช้ -fsanitize = undefined เอกสารการเปลี่ยนแปลงเรียกสิ่งนี้ว่าเป็นอันตรายอย่างชัดเจนเพราะแบ่งรหัสที่ใช้บ่อยเป็นจำนวนมากอย่างน่าประหลาดใจ เหตุใดสมมติฐานใหม่นี้จึงไม่ใช้งานรหัส C ++ ที่ใช้งานได้จริง มีรูปแบบเฉพาะหรือไม่ที่โปรแกรมเมอร์ไม่ประมาทหรือไม่มีข้อมูลจะพึ่งพาพฤติกรรมที่ไม่ได้กำหนดนี้หรือไม่? ฉันไม่สามารถจินตนาการได้ว่ามีใครเขียนif (this == NULL)เพราะมันแปลกประหลาดมาก

6
ทำไมจำนวนเต็มล้นใน x86 กับ GCC ทำให้เกิดการวนซ้ำไม่สิ้นสุด?
รหัสต่อไปนี้จะเข้าสู่วงวนไม่สิ้นสุดบน GCC: #include <iostream> using namespace std; int main(){ int i = 0x10000000; int c = 0; do{ c++; i += i; cout << i << endl; }while (i > 0); cout << c << endl; return 0; } ดังนั้นนี่คือข้อตกลง: การล้นจำนวนเต็มที่ลงนามคือพฤติกรรมที่ไม่ได้กำหนดทางเทคนิค แต่ GCC บน x86 ใช้เลขคณิตจำนวนเต็มโดยใช้คำแนะนำจำนวนเต็ม x86 - ซึ่งตัดกับโอเวอร์โฟลว์ ดังนั้นฉันคาดหวังว่ามันจะห่อหุ้มด้วยน้ำล้น …
129 c++  c  gcc  x86  undefined-behavior 

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