เหตุใดฉันจึงควรเปิดใช้งานคำเตือนคอมไพเลอร์เสมอ


302

ฉันมักจะได้ยินว่าเมื่อรวบรวมโปรแกรม C และ C ++ ฉันควร "เปิดใช้งานคำเตือนคอมไพเลอร์" เสมอ ทำไมถึงจำเป็น ฉันจะทำอย่างไร

บางครั้งฉันก็ได้ยินว่าฉันควร "ถือว่าคำเตือนเป็นข้อผิดพลาด" ฉันควร? ฉันจะทำอย่างไร

คำตอบ:


341

ทำไมจึงเปิดใช้งานคำเตือน?

คอมไพเลอร์ C และ C ++ ไม่ดีอย่างมากที่รายงานข้อผิดพลาดทั่วไปของโปรแกรมเมอร์โดยค่าเริ่มต้นเช่น:

  • ลืมที่จะเริ่มต้นตัวแปร
  • ลืมreturnค่าจากฟังก์ชั่น
  • อาร์กิวเมนต์ในprintfและscanfตระกูลที่ไม่ตรงกับสตริงรูปแบบ
  • ฟังก์ชั่นการใช้งานโดยไม่ต้องประกาศล่วงหน้า (C เท่านั้น)

สิ่งเหล่านี้สามารถตรวจพบและรายงานโดยปกติแล้วจะไม่ได้รับการตั้งค่า คุณสมบัตินี้ต้องได้รับการร้องขออย่างชัดเจนผ่านตัวเลือกคอมไพเลอร์

วิธีเปิดใช้งานคำเตือน?

ขึ้นอยู่กับคอมไพเลอร์ของคุณ

ไมโครซอฟท์ C และ C ++ คอมไพเลอร์สวิทช์เข้าใจชอบ/W1, /W2, /W3, และ/W4 ใช้เวลาอย่างน้อย/Wall และอาจปล่อยคำเตือนปลอมสำหรับไฟล์ส่วนหัวของระบบ แต่ถ้าโครงการของคุณคอมไพล์อย่างสมบูรณ์ด้วยหนึ่งในตัวเลือกเหล่านี้ไปได้เลย ตัวเลือกเหล่านี้ไม่สามารถใช้ร่วมกันได้/W3/W4/Wall

ส่วนใหญ่คอมไพเลอร์อื่น ๆ เข้าใจตัวเลือกเช่น-Wall, และ-Wpedantic เป็นสิ่งจำเป็นและส่วนที่เหลือทั้งหมดได้รับการแนะนำ (โปรดทราบว่าแม้จะมีชื่อแต่ก็สามารถเปิดใช้งานการเตือนที่สำคัญที่สุดเท่านั้นไม่ใช่ทั้งหมด ) ตัวเลือกเหล่านี้สามารถใช้แยกกันหรือรวมเข้าด้วยกัน-Wextra-Wall-Wall

IDE ของคุณอาจมีวิธีการเปิดใช้งานสิ่งเหล่านี้จากส่วนต่อประสานผู้ใช้

เหตุใดจึงถือว่าคำเตือนเป็นข้อผิดพลาด พวกเขาเป็นเพียงคำเตือน!

คำเตือนคอมไพเลอร์ส่งสัญญาณว่าอาจมีปัญหาร้ายแรงในรหัสของคุณ ปัญหาที่กล่าวข้างต้นมักเป็นอันตรายถึงชีวิต คนอื่นอาจจะใช่หรือไม่ใช่ แต่คุณต้องการให้การรวบรวมล้มเหลวแม้ว่ามันจะเป็นสัญญาณเตือนที่ผิดพลาดก็ตาม ตรวจสอบคำเตือนแต่ละรายการค้นหาสาเหตุที่แท้จริงและแก้ไข ในกรณีที่มีการเตือนที่ผิดพลาดให้หลีกเลี่ยง - นั่นคือใช้คุณสมบัติภาษาอื่นหรือสร้างเพื่อไม่ให้มีการเตือนอีกต่อไป หากนี่พิสูจน์ได้ว่าเป็นเรื่องยากมากให้ปิดใช้งานคำเตือนนั้นเป็นราย ๆ ไป

คุณไม่ต้องการเพียงแค่ปล่อยให้คำเตือนเป็นคำเตือนแม้ว่าพวกเขาทั้งหมดจะเป็นสัญญาณเตือนที่ผิดพลาด มันอาจจะโอเคสำหรับโครงการขนาดเล็กมากซึ่งจำนวนคำเตือนทั้งหมดที่ปล่อยออกมาน้อยกว่า 7 มีอะไรเพิ่มเติมและมันง่ายสำหรับการเตือนใหม่ที่จะหลงทางในเหตุการณ์ที่คุ้นเคยเก่า ๆ ไม่อนุญาต เพียงทำให้โครงการทั้งหมดของคุณรวบรวมได้อย่างหมดจด

หมายเหตุสิ่งนี้ใช้กับการพัฒนาโปรแกรม หากคุณกำลังปล่อยโปรเจ็กต์ของคุณสู่โลกในรูปแบบของแหล่งที่มามันอาจเป็นความคิดที่ดีที่จะไม่จัดหา-Werrorหรือเทียบเท่าในสคริปต์สร้างของคุณที่วางจำหน่าย ผู้คนอาจพยายามสร้างโครงการของคุณด้วยคอมไพเลอร์เวอร์ชันอื่นหรือคอมไพเลอร์ที่แตกต่างกันโดยสิ้นเชิงซึ่งอาจเปิดใช้คำเตือนชุดอื่น คุณอาจต้องการสร้างงานให้สำเร็จ ยังคงเป็นความคิดที่ดีที่จะเปิดใช้งานคำเตือนเพื่อให้ผู้ที่เห็นข้อความเตือนสามารถส่งรายงานข้อผิดพลาดหรือแพตช์ให้คุณได้

วิธีการจัดการคำเตือนว่าเป็นข้อผิดพลาด?

สิ่งนี้จะทำอีกครั้งด้วยสวิตช์คอมไพเลอร์ /WXสำหรับไมโครซอฟท์คนอื่น ๆ -Werrorส่วนใหญ่ใช้ ไม่ว่าในกรณีใดการรวบรวมข้อมูลจะล้มเหลวหากมีคำเตือนเกิดขึ้น


107
ฉันโพสต์คำถามและคำตอบนี้เพราะฉันป่วยและเบื่อที่จะบอกคนอื่นให้เปิดใช้งานคำเตือน ตอนนี้ฉันสามารถชี้พวกเขาได้ที่นี่ (หรือถ้าฉันอยู่ในอารมณ์ชั่วร้ายเป็นพิเศษให้ปิดคำถามของพวกเขาในฐานะผู้ล่อลวง) คุณสามารถปรับปรุงคำตอบนี้หรือเพิ่มของคุณเอง!
n คำสรรพนาม 'm

16
นอกจากนี้คุณยังสามารถใช้เสียงดังกราว
สิ่งของทุกอย่าง

9
ตัวดัดแปลงเดียวที่ฉันเพิ่มคือคำเตือนบางอย่างอาจไม่เป็นประโยชน์สำหรับแอปพลิเคชันของคุณ (ฉันเคยเห็นคำเตือนว่าคอมไพเลอร์เพิ่ม padding 2 ไบต์ระหว่างองค์ประกอบใน struct แอปพลิเคชันสำหรับการสร้างต้นแบบดังนั้นหน่วยความจำที่สูญเสียไปเล็กน้อยไม่ได้รบกวนเราเลย) ปฏิบัติต่อคำเตือนทั้งหมดว่าเป็นข้อผิดพลาด คุณรู้ว่าทำไมคำเตือนนั้นไม่ช่วยคุณ
Kyle A

20
ข้อเสียของการปฏิบัติต่อคำเตือนเป็นข้อผิดพลาดสำหรับคนที่ทำตามคำแนะนำในการสร้างเริ่มต้นของคุณคือรหัสของคุณเน่าเป็นคอมไพเลอร์เพิ่มคำเตือนใหม่ ผู้ใช้ที่ดาวน์โหลดรหัสของคุณและลองสร้างมันในอนาคตอาจไม่สามารถทำได้เพราะคอมไพเลอร์ของพวกเขานั้นใหม่เกินไปและออกคำเตือนเกี่ยวกับวงเล็บพิเศษหรือสิ่งที่คอมไพเลอร์ของคุณไม่สนใจ ผู้ใช้ที่พบข้อผิดพลาดจะไม่รับผิดชอบต่อรหัสของคุณหรือระบบการสร้างของคุณและไม่มีความคิดวิธีปิดการใช้คำเตือนเป็นข้อผิดพลาดและสร้างโครงการของคุณจริง ๆ
interfect

15
@ ข้อบกพร่องใช่นี่เกิดขึ้นกับฉันสองสามครั้ง ไม่มีปัญหา หากคุณเลือกที่จะสร้างunmaintainedชิ้นส่วนของซอฟต์แวร์ที่ใช้คอมไพเลอร์มันก็ไม่เคยผ่านการทดสอบด้วยดีคุณควรที่จะมีการเตรียมที่จะทำบาง mainenance ตัวเอง
n คำสรรพนาม 'm

94

C คือชื่อเสียงภาษาระดับค่อนข้างต่ำเป็น HLLs ไป C ++ ถึงแม้ว่ามันอาจจะเป็นภาษาระดับสูงกว่า C มาก แต่ก็ยังคงแบ่งลักษณะไว้เป็นจำนวนมาก และหนึ่งในคุณลักษณะเหล่านั้นคือภาษาที่ถูกออกแบบโดยโปรแกรมเมอร์สำหรับโปรแกรมเมอร์ - และโดยเฉพาะโปรแกรมเมอร์ที่รู้ว่าพวกเขากำลังทำอะไร

[สำหรับส่วนที่เหลือของคำตอบนี้ฉันจะให้ความสำคัญกับ C. สิ่งที่ฉันจะพูดส่วนใหญ่จะใช้กับ C ++ ด้วยแม้ว่าอาจจะไม่รุนแรงก็ตาม แม้ว่าในขณะที่ Bjarne Stroustrup ได้กล่าวถึงชื่อเสียงว่า"C ทำให้มันง่ายในการถ่ายภาพตัวเองที่เท้า C ++ ทำให้มันยากขึ้น ]

ถ้าคุณรู้ว่าสิ่งที่คุณกำลังทำ - จริงๆรู้ว่าสิ่งที่คุณกำลังทำ - บางครั้งคุณอาจจะต้อง "แหกกฎ" แต่ส่วนใหญ่เราส่วนใหญ่จะยอมรับว่ากฎที่เจตนาดีช่วยให้เราหมดปัญหาและการละเมิดกฎเหล่านั้นตลอดเวลาเป็นความคิดที่ไม่ดี

แต่ใน C และ C ++ มีหลายสิ่งหลายอย่างที่คุณสามารถทำได้นั่นคือ "ความคิดที่ไม่ดี" แต่สิ่งที่ไม่เป็นทางการ "กับกฎ" บางครั้งพวกเขาก็เป็นความคิดที่ไม่ดีบางครั้ง (แต่อาจจะป้องกันได้อีกครั้ง); บางครั้งพวกเขาก็เป็นความคิดที่ไม่ดีตลอดเวลา แต่ประเพณีก็ไม่ได้เตือนเสมอเกี่ยวกับสิ่งเหล่านี้ - เพราะอีกครั้งข้อสันนิษฐานคือโปรแกรมเมอร์รู้ว่าพวกเขากำลังทำอะไรพวกเขาจะไม่ทำสิ่งเหล่านี้โดยไม่มีเหตุผลที่ดีพวกเขาจะรำคาญโดยกลุ่ม คำเตือนที่ไม่จำเป็น

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

ท้ายที่สุดประสบการณ์ได้แสดงให้เห็นแล้วว่าโปรแกรมเมอร์ไม่ได้ทำผิดพลาด แต่ความผิดพลาดเหล่านี้อาจมีผลที่ตามมาอย่างแท้จริง หากคุณทำผิดพลาดและคอมไพเลอร์ไม่เตือนคุณเกี่ยวกับมันและอย่างใดโปรแกรมไม่ผิดพลาดทันทีหรือทำอะไรผิดอย่างเห็นได้ชัดเพราะมันความผิดพลาดสามารถแฝงตัวอยู่ที่นั่นซ่อนบางครั้งเป็นเวลาหลายปีจนกว่ามันจะทำให้จริงๆปัญหาใหญ่

ดังนั้นปรากฎว่าส่วนใหญ่คำเตือนเป็นความคิดที่ดีหลังจากทั้งหมด แม้แต่โปรแกรมเมอร์ที่มีประสบการณ์ก็เรียนรู้ (ที่จริงแล้วมันคือ " โดยเฉพาะโปรแกรมเมอร์ที่มีประสบการณ์ได้เรียนรู้") ว่าคำเตือนมีแนวโน้มที่จะดีกว่าอันตราย สำหรับทุกครั้งที่คุณทำสิ่งผิดพลาดโดยเจตนาและคำเตือนเป็นเรื่องน่ารำคาญอาจมีอย่างน้อยสิบครั้งที่คุณทำสิ่งผิดพลาดโดยบังเอิญและคำเตือนช่วยให้คุณรอดจากปัญหาอื่น ๆ และคำเตือนส่วนใหญ่สามารถปิดใช้งานหรือแก้ไขได้ในช่วงเวลาที่คุณต้องการทำสิ่งที่ "ผิด" จริงๆ

(ตัวอย่างคลาสสิกเช่น "ความผิดพลาด" คือการทดสอบif(a = b)ส่วนใหญ่เวลานี้เป็นข้อผิดพลาดดังนั้นคอมไพเลอร์มากที่สุดวันนี้เตือนเกี่ยวกับมัน -.. บางคนโดยค่าเริ่มต้น แต่ถ้าคุณจริงๆอยากจะกำหนดทั้งbไปaและการทดสอบ ผลลัพธ์คุณสามารถปิดใช้งานคำเตือนโดยพิมพ์if((a = b)))

คำถามที่สองคือทำไมคุณต้องการถามคอมไพเลอร์ให้ปฏิบัติต่อคำเตือนว่าเป็นข้อผิดพลาด? ฉันบอกว่ามันเป็นเพราะธรรมชาติของมนุษย์โดยเฉพาะปฏิกิริยาที่ง่ายเกินไปในการพูดว่า "โอ้นั่นเป็นเพียงคำเตือนนั่นไม่สำคัญเลยฉันจะทำความสะอาดในภายหลัง" แต่ถ้าคุณเป็น procrastinator (และฉันไม่รู้เกี่ยวกับคุณ แต่ฉันเป็นprocrastinator ที่แย่มาก ) มันง่ายที่จะกำจัดการทำความสะอาดที่จำเป็นโดยทั่วไป - และถ้าคุณติดนิสัยการเพิกเฉยต่อคำเตือน รับง่ายขึ้นและง่ายขึ้นที่จะพลาดข้อความเตือนสำคัญที่กำลังนั่งอยู่ไม่มีใครสังเกตเห็นท่ามกลางสิ่งที่คุณไม่สนใจ

ดังนั้นการขอให้คอมไพเลอร์ปฏิบัติต่อคำเตือนเนื่องจากข้อผิดพลาดเป็นเคล็ดลับเล็ก ๆ น้อย ๆ ที่คุณสามารถเล่นด้วยตัวคุณเองเพื่อกำจัดมนุษย์คนนี้

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


9
"โปรแกรมเมอร์ที่รู้ว่าพวกเขากำลังทำอะไรอยู่" - ฮ่า ๆ มีการเข้าใจผิด "ไม่จริงสกอต" ถ้าฉันเคยเห็น :) :)
46932

3
@Dancrumb LOL กลับ atcha ฉันไม่เคยแน่ใจเลยว่าฉันเข้าใจการเข้าใจผิดที่ไม่ใช่สกอตจริงแต่ฉันชอบมันดังนั้นนี่จะเป็นการออกกำลังกายที่ดีสำหรับฉัน ฉันเดาว่าแอปพลิเคชันที่นี่มีลักษณะเช่นนี้: "ไม่มีโปรแกรมเมอร์ C คนไหนที่จะเขียนif(a = b)ได้ดังนั้นเราจึงไม่จำเป็นต้องเตือนเรื่องนี้" (มีคนสร้างรายการข้อผิดพลาดร้ายแรง 10 รายการใน 10 ผลิตภัณฑ์ที่วางจำหน่ายซึ่งเป็นผลมาจากข้อผิดพลาดนี้) "โอเคไม่มีโปรแกรมเมอร์ C ที่มีประสบการณ์จะเขียนว่า ... "
Steve Summit

3
@SteveSummit แต่โปรแกรมเมอร์ C ที่มีประสบการณ์จริงๆอาจเขียนif (returnCodeFromFoo = foo(bar))และหมายถึงมันเพื่อจับและทดสอบโค้ดในที่เดียว (สมมติว่าจุดประสงค์เดียวของfooการมีผลข้างเคียง!) ความจริงที่ว่าโปรแกรมเมอร์ที่มีประสบการณ์จริงๆอาจรู้ว่านี่ไม่ใช่ สไตล์การเขียนโค้ดที่ดีนั้นอยู่ด้านข้างจุด)
alephzero

5
สิ่งคือโปรแกรมเมอร์ที่มีประสบการณ์มากที่สุดจะเปิดใช้งานคำเตือนส่วนใหญ่หากไม่ใช่ทั้งหมด หากพวกเขาต้องการใช้สิ่งที่ชอบif (returnCodeFromFoo = foo(bar))พวกเขาก็ใส่ความคิดเห็นและปิดคำเตือน (เพื่อให้เมื่อโปรแกรมเมอร์บำรุงรักษามองมันในอีก 4 ปีต่อมาเขา / เธอจะรู้ว่ารหัสนั้นเป็นความตั้งใจนั่นคือฉันทำงาน กับคนที่อยู่ใน (ในที่ดินของ Microsoft C ++) ยืนยันว่าการรวม / Wall กับการจัดการคำเตือนเป็นข้อผิดพลาดเป็นวิธีที่จะไปเอ่อมันไม่ได้ (เว้นแต่คุณต้องการใส่ความคิดเห็นในการปราบปรามจำนวนมาก)
Flydog57

3
ในฐานะที่เป็นคนที่ไม่ได้เขียนรหัสในชีวิตประจำวัน แต่เมื่อฉันทำมันมักจะเป็นโลหะเปลือย (มักจะอยู่ในคณะกรรมการการออกแบบของฉันเอง) ฉันพบคำเตือนที่ทรงคุณค่า เมื่อบรรจุค่าลงในการลงทะเบียนภายใน (สำหรับตำแหน่งตัวบอก DMA เป็นตัวอย่าง) คำเตือนเกี่ยวกับการแปลงเป็นตัวชี้หมายถึงฉันทำการส่งเพื่อล้างคำเตือน มันจะไม่เป็นข้อผิดพลาด แต่ถ้ามีคนอื่น (หรือแม้แต่ตัวฉันเอง!) หยิบรหัสนั้นในอีกไม่กี่เดือนมันอาจสร้างความสับสนได้ นอกจากนี้ฉันใช้กฎปัจจุบันไม่มีคำเตือนกับผลลัพธ์ของเครื่องมือ CAD ของฉันเช่นกัน
ปีเตอร์สมิ ธ

39

คำเตือนประกอบด้วยคำแนะนำที่ดีที่สุดนักพัฒนา C ++ ที่มีทักษะมากที่สุดสามารถอบเข้าไปในแอปพลิเคชัน พวกเขาน่าจะเก็บไว้รอบ ๆ

C ++ ซึ่งเป็นภาษาทัวริงที่สมบูรณ์มีหลายกรณีที่คอมไพเลอร์ต้องเชื่อมั่นว่าคุณรู้ว่าคุณกำลังทำอะไรอยู่ อย่างไรก็ตามมีหลายกรณีที่คอมไพเลอร์สามารถตระหนักได้ว่าคุณอาจไม่ได้ตั้งใจจะเขียนสิ่งที่คุณเขียน ตัวอย่างคลาสสิกเป็น printf () รหัสซึ่งไม่ตรงกับข้อโต้แย้งหรือมาตรฐาน :: สตริงส่งผ่านไปยัง printf (ไม่ได้ว่าเคยเกิดขึ้นกับฉัน!) ในกรณีเหล่านี้รหัสที่คุณเขียนไม่ใช่ข้อผิดพลาด เป็นนิพจน์ C ++ ที่ถูกต้องพร้อมการตีความที่ถูกต้องเพื่อให้คอมไพเลอร์ดำเนินการ แต่คอมไพเลอร์มีลางสังหรณ์ที่แข็งแกร่งซึ่งคุณมองข้ามบางสิ่งซึ่งเป็นเรื่องง่ายสำหรับคอมไพเลอร์สมัยใหม่ในการตรวจจับ นี่คือคำเตือน พวกเขาเป็นสิ่งที่เห็นได้ชัดกับคอมไพเลอร์โดยใช้กฎที่เข้มงวดของ C ++ ในการกำจัดของที่คุณอาจมองข้าม

การปิดคำเตือนหรือเพิกเฉยต่อคำเตือนนั้นก็เหมือนกับการเลือกที่จะเพิกเฉยต่อคำแนะนำฟรีจากผู้ที่มีทักษะมากกว่าคุณ มันเป็นบทเรียนในฮูเบอร์ที่จบลงเมื่อคุณบินใกล้กับดวงอาทิตย์และปีกของคุณละลายมากเกินไปหรือเกิดข้อผิดพลาดเกี่ยวกับความจำเสื่อม ระหว่างสองฉันจะตกลงมาจากท้องฟ้าทุกวัน!

"ปฏิบัติต่อคำเตือนว่าเป็นข้อผิดพลาด" เป็นรุ่นที่สูงที่สุดของปรัชญานี้ ความคิดที่นี่คือคุณแก้ไขทุกคำเตือนคอมไพเลอร์ให้คุณ - คุณฟังคำแนะนำฟรีทุกบิตและดำเนินการกับมัน ไม่ว่าจะเป็นรูปแบบที่ดีสำหรับการพัฒนาสำหรับคุณขึ้นอยู่กับทีมและผลิตภัณฑ์ที่คุณกำลังทำงานอยู่ มันเป็นวิธีการที่นักพรตที่พระอาจมี สำหรับบางคนมันใช้งานได้ดี สำหรับคนอื่นมันไม่ได้

ในแอปพลิเคชันของฉันจำนวนมากเราไม่ถือว่าคำเตือนเป็นข้อผิดพลาด เราทำเช่นนี้เพราะแอปพลิเคชันเหล่านี้จำเป็นต้องรวบรวมในหลาย ๆ แพลตฟอร์มที่มีคอมไพเลอร์หลายช่วงอายุที่แตกต่างกัน บางครั้งเราพบว่าเป็นไปไม่ได้ที่จะแก้ไขคำเตือนในด้านหนึ่งโดยที่มันไม่ได้เปลี่ยนเป็นการเตือนบนแพลตฟอร์มอื่น ดังนั้นเราแค่ระวัง เราเคารพคำเตือน แต่เราไม่โค้งไปข้างหลังสำหรับพวกเขา


11
สิ่ง C + + กำลังทัวริงสมบูรณ์เกี่ยวข้องกับที่ มีหลายภาษาที่ทัวริงสมบูรณ์และไม่ไว้ใจคุณถ้าคุณทำอะไรผิด ....
ลา SE

3
@KamiKaze ทุกภาษาจะมีข้อผิดพลาดที่เป็นสำนวน (เช่น Java ไม่สามารถหยุดคุณเขียนที่ไม่สอดคล้องequals/ hashCode) และเป็นปัญหาคุณภาพของการใช้งานที่มีการรายงาน
Caleth

2
@KamiKaze บิตทัวริงสมบูรณ์มาเพื่อแสดงให้เห็นว่ามีบางกรณีที่คอมไพเลอร์ไม่สามารถพิสูจน์ได้ว่ารหัสของคุณจะล้มเหลวในการทำงานตามแผนที่วางไว้ สิ่งนี้มีความสำคัญเนื่องจากคอมไพเลอร์ไม่สามารถทำให้รหัส "ผิด" ทั้งหมดผิดพลาดได้ ข้อผิดพลาดสามารถสงวนไว้สำหรับพฤติกรรมที่นักออกแบบภาษามั่นใจได้เสมอว่า "ผิด" (โดยทั่วไปเนื่องจากจะนำไปสู่เส้นทางที่ไม่สอดคล้องกัน)
Cort Ammon

2
ซึ่งชี้ไปที่ความท้าทายด้วย "คำเตือนทั้งหมดเป็นข้อผิดพลาด" คำเตือนคือโดยการออกแบบให้มีโอกาสมากขึ้นทำให้เกิดการเรียกใช้โค้ดที่ถูกต้องบางอย่างเพื่อแลกกับการเรียกใช้โค้ดที่ผิดบ่อยขึ้น คำเตือนเนื่องจากข้อผิดพลาดทำให้คุณไม่สามารถใช้ความสามารถของภาษาแบบเต็ม
Cort Ammon

2
อย่างไรก็ตามโดยทั่วไปโปรแกรมเมอร์ต้องการภาษาที่มากกว่าสิ่งที่ "ปลอดภัย" เราต้องการภาษาที่ทำในสิ่งที่เราคิดว่าเราบอกให้ทำ ดังนั้นคำเตือนยังคงสำคัญเนื่องจากคลาสจริงของสิ่งที่เราต้องการให้คอมพิวเตอร์ทำคือคลาส semantic คอมไพเลอร์สามารถเลือกได้โดยกำหนด "ไม่ถูกต้อง" หรือ "ไม่ปลอดภัย" แต่ในที่สุดคุณก็ยังมีซูเปอร์คลาสของพฤติกรรมที่โปรแกรมเมอร์ต้องการให้โปรแกรมทำ คำเตือนช่วยลดระดับซูเปอร์คลาสให้แคบลง
Cort Ammon

19

การจัดการคำเตือนไม่เพียงทำให้โค้ดดีขึ้นเท่านั้น แต่ยังทำให้คุณเป็นโปรแกรมเมอร์ที่ดีขึ้นอีกด้วย คำเตือนจะบอกคุณเกี่ยวกับสิ่งต่าง ๆ ที่อาจดูเล็กน้อยสำหรับคุณในวันนี้ แต่วันหนึ่งนิสัยที่ไม่ดีจะกลับมากัดหัวของคุณ

ใช้ประเภทที่ถูกต้องส่งคืนค่านั้นประเมินค่าที่ส่งคืน ใช้เวลาและใคร่ครวญว่า "นี่เป็นประเภทที่ถูกต้องจริงๆในบริบทนี้หรือไม่" "ฉันต้องส่งคืนสิ่งนี้หรือไม่" และตัวใหญ่; "รหัสนี้จะพกพาได้ในอีก 10 ปีข้างหน้าหรือไม่"

เริ่มเขียนโค้ดที่ไม่มีคำเตือนตั้งแต่แรก


17

คำตอบอื่น ๆ นั้นยอดเยี่ยมและฉันไม่ต้องการพูดซ้ำสิ่งที่พวกเขาพูด

อีกแง่มุมหนึ่งของ "ทำไมจึงเปิดใช้งานคำเตือน" ที่ไม่ได้สัมผัสอย่างถูกต้องคือพวกเขาช่วยอย่างมากกับการบำรุงรักษาโค้ด เมื่อคุณเขียนโปรแกรมที่มีขนาดใหญ่มันเป็นไปไม่ได้เลยที่จะเก็บเรื่องทั้งหมดไว้ในหัวของคุณทันที โดยทั่วไปคุณมีฟังก์ชั่นหรือสามอย่างที่คุณกำลังเขียนและคิดอย่างแข็งขันและอาจเป็นไฟล์หรือสามบนหน้าจอที่คุณสามารถอ้างถึงได้ แต่ส่วนใหญ่ของโปรแกรมอยู่ในพื้นหลังและคุณต้องเชื่อมั่น ทำงานต่อไป

การมีคำเตือนและทำให้พวกเขากระตือรือร้นและอยู่ในใบหน้าของคุณให้มากที่สุดจะช่วยเตือนคุณหากสิ่งที่คุณเปลี่ยนมีปัญหากับบางสิ่งที่คุณมองไม่เห็น

-Wswitch-enumใช้ตัวอย่างเช่นคำเตือนเสียงดังกราว สิ่งนั้นจะเป็นตัวเตือนถ้าคุณใช้สวิตช์บน enum และพลาดหนึ่งในค่า enum ที่เป็นไปได้ เป็นสิ่งที่คุณอาจคิดว่าเป็นความผิดพลาดที่ไม่น่าจะเกิดขึ้น: อย่างน้อยคุณอาจดูรายการค่า enum เมื่อคุณเขียนคำสั่ง switch คุณอาจมี IDE ที่สร้างตัวเลือกสวิตช์ให้คุณโดยไม่มีที่ว่างสำหรับความผิดพลาดของมนุษย์

คำเตือนนี้มาเป็นของตัวเองเมื่อหกเดือนต่อมาคุณเพิ่มอีกรายการที่เป็นไปได้เพื่อ enum อีกครั้งหากคุณกำลังคิดเกี่ยวกับรหัสที่เป็นปัญหาคุณอาจไม่เป็นอะไร แต่ถ้า enum นี้ใช้เพื่อจุดประสงค์ที่แตกต่างกันและเป็นหนึ่งในสิ่งที่คุณต้องการตัวเลือกพิเศษมันง่ายมากที่จะลืมอัปเดตสวิตช์ในไฟล์ที่คุณไม่ได้สัมผัสเป็นเวลา 6 เดือน

คุณสามารถนึกถึงคำเตือนในลักษณะเดียวกับที่คุณนึกถึงกรณีทดสอบอัตโนมัติ: ช่วยให้คุณมั่นใจได้ว่ารหัสนั้นสมเหตุสมผลและทำในสิ่งที่คุณต้องการเมื่อคุณเขียนครั้งแรก แต่ช่วยได้มากขึ้นเพื่อให้แน่ใจว่า ทำสิ่งที่คุณต้องการต่อไปในขณะที่คุณแยงมัน ความแตกต่างคือกรณีทดสอบนั้นแคบมากตามความต้องการของรหัสของคุณและคุณต้องเขียนพวกเขาในขณะที่คำเตือนนั้นทำงานได้มาตรฐานที่สมเหตุสมผลสำหรับรหัสเกือบทั้งหมดและพวกเขาได้รับแรงบันดาลใจจาก boffins ที่ทำคอมไพล์


9
อีกวิธีที่พวกเขาช่วยในการบำรุงรักษาคือเมื่อคุณดูรหัสของผู้อื่นและไม่สามารถบอกได้ว่าผลข้างเคียงนั้นเกิดจากความตั้งใจหรือไม่ ด้วยคำเตือนเมื่อคุณรู้ว่าพวกเขารู้ปัญหาอย่างน้อย
Robin Bennett

หรือในกรณีของฉันคุณนำเข้าไฟล์จากระบบฝังตัวที่มีคำสั่งสลับบรรทัด 3000+ บน enum ที่มีค่าหลายพันค่า คำเตือน "ตกหลุม" (หลีกเลี่ยงโดยใช้ goto) ปิดบังข้อบกพร่อง "ที่ไม่ได้จัดการ" จำนวนหนึ่ง ... คอมไพเลอร์แบบฝังไม่ได้ปล่อยสิ่งใดสิ่งหนึ่ง แต่ข้อผิดพลาดมีความสำคัญอย่างไรก็ตาม
Móż

15

คำเตือนที่ไม่ได้รับการแก้ไขจะไม่ช้าก็เร็ว, นำไปสู่ข้อผิดพลาดในรหัสของคุณ


ตัวอย่างเช่นการดีบักความผิดพลาดในการแบ่งส่วนต้องการให้โปรแกรมเมอร์ทำการติดตามรูท (สาเหตุ) ของความผิดปกติซึ่งมักจะอยู่ในตำแหน่งก่อนหน้าในรหัสของคุณมากกว่าบรรทัดที่ทำให้เกิดความผิดพลาดในการแบ่งส่วน

เป็นเรื่องปกติมากที่สาเหตุเป็นบรรทัดที่คอมไพเลอร์ได้ออกคำเตือนว่าคุณไม่สนใจและบรรทัดที่ทำให้การแบ่งเซ็กเมนต์เกิดความผิดพลาดบรรทัดที่โยนข้อผิดพลาดในที่สุด

การแก้ไขคำเตือนนำไปสู่การแก้ไขปัญหา .. คลาสสิก!

การสาธิตด้านบน .. พิจารณารหัสต่อไปนี้:

#include <stdio.h>

int main(void) {
  char* str = "Hello world!";
  int idx;

  // Colossal amount of code here, irrelevant to 'idx'

  printf("%c\n", str[idx]);

  return 0;
}

ซึ่งเมื่อคอมไพล์ด้วยแฟล็ก "Wextra" ที่ส่งผ่านไปยัง GCC จะให้

main.c: In function 'main':
main.c:9:21: warning: 'idx' is used uninitialized in this function [-Wuninitialized]
    9 |   printf("%c\n", str[idx]);
      |                     ^

ซึ่งฉัน สามารถละเว้นและรันรหัสต่อไป .. และจากนั้นฉันจะได้เห็นข้อผิดพลาดการแบ่งส่วน "ยิ่งใหญ่" เนื่องจากศาสตราจารย์ epicurus IP ของฉันเคยพูดว่า:

การแบ่งส่วนความผิด

ในการแก้ไขข้อบกพร่องในสถานการณ์โลกแห่งความเป็นจริงใครจะเริ่มจากบรรทัดที่ทำให้เกิดการแบ่งส่วนและพยายามที่จะติดตามว่าอะไรคือสาเหตุของสาเหตุ ... พวกเขาจะต้องค้นหาสิ่งที่เกิดขึ้น iและstrภายในว่าจำนวนเงินมหาศาล ของรหัสที่นั่น ...

จนกระทั่งวันหนึ่งพวกเขาพบว่าตนเองอยู่ในสถานการณ์ที่พวกเขาค้นพบสิ่งนั้น idxมีการใช้งานที่ไม่ได้กำหนดค่าเริ่มต้นดังนั้นจึงมีค่าขยะซึ่งส่งผลให้มีการจัดทำดัชนีสตริง (วิธี) เกินขอบเขตซึ่งนำไปสู่

หากเพียง แต่พวกเขาไม่เพิกเฉยต่อคำเตือนพวกเขาก็จะพบข้อผิดพลาดทันที!


4
ถึงชื่อของคุณ: ไม่จำเป็น ตัวอย่างเช่นคำเตือนที่แนะนำให้ใช้วงเล็บในสูตรที่ไม่ต้องการให้พวกเขาชี้ไปที่ปัญหาที่ไม่เคยทำให้เกิดข้อผิดพลาด ตัวนำหน้าในภาษาการเขียนโปรแกรมที่กำหนดไม่เปลี่ยนแปลง เคย.
Marc van Leeuwen

4
@MarcvanLeeuwen ตัวอย่างที่คุณอ้างถึง สามารถเปลี่ยนเป็นข้อผิดพลาดโทได้เช่นหากโปรแกรมเมอร์ผู้ที่จำไม่ได้ว่าลำดับความสำคัญของโอเปอเรเตอร์ถูกต้องแก้ไขสูตรเล็กน้อย คำเตือนบอกคุณว่า: "อาจไม่ชัดเจนสำหรับบางคนเพิ่มวงเล็บบางส่วนเพื่อให้ชัดเจนยิ่งขึ้น" แม้ว่าจะต้องยอมรับว่าชื่อของโพสต์ต้นฉบับนั้นไม่เป็นความจริงเสมอไป
Hubert Jasieniecki

^ สิ่งใดสามารถกลายเป็นข้อผิดพลาด เป็นเรื่องง่ายที่จะแนะนำบั๊กในโค้ดที่ถูกวงเล็บบางส่วนเหมือนกับโค้ดที่ถูกวงเล็บอย่างสมบูรณ์
Jim Balter

... นอกจากนี้ฉันมีคำถามสำหรับผู้ดีบักซึ่งมีปฏิกิริยาแรกกับ "โอ้มันแยกจากstr[idx]" ไม่ใช่ "โอเคอยู่ที่ไหนstrและidxถูกกำหนดหรือไม่`
Justin Time - Reinstate Monica

2
คุณโชคดีถ้าคุณได้รับข้อผิดพลาดในการแบ่งกลุ่ม หากคุณโชคดีน้อยลงคุณอาจมีโอกาสidxเป็นค่าที่คุณคาดหวังจากการทดสอบของคุณ (ไม่น่าเป็นไปได้ถ้าค่าที่คาดไว้คือ 0) และจริง ๆ แล้วชี้ไปที่ข้อมูลสำคัญที่ไม่ควรพิมพ์เมื่อนำไปใช้งาน
celtschk

14

การปฏิบัติตามคำเตือนเป็นข้อผิดพลาดเป็นเพียงวิธีการมีวินัยในตนเอง: คุณได้รวบรวมโปรแกรมเพื่อทดสอบคุณลักษณะใหม่ที่เป็นประกาย แต่คุณทำไม่ได้จนกว่าคุณจะแก้ไขส่วนที่เลอะเทอะ ไม่มีข้อมูลเพิ่มเติมใดWerrorๆ เพียงกำหนดลำดับความสำคัญอย่างชัดเจน:

อย่าเพิ่มรหัสใหม่จนกว่าคุณจะแก้ไขปัญหาในรหัสที่มีอยู่

มันเป็นความคิดที่สำคัญไม่ใช่เครื่องมือ เอาต์พุตการวินิจฉัยคอมไพเลอร์เป็นเครื่องมือ MISRA (สำหรับ C ที่ฝัง) เป็นเครื่องมืออื่น มันไม่สำคัญว่าคุณจะใช้แบบไหน แต่คำเตือนของคอมไพเลอร์เป็นเครื่องมือที่ง่ายที่สุดที่คุณจะได้รับ (เป็นเพียงหนึ่งการตั้งค่า) และอัตราส่วนสัญญาณต่อสัญญาณรบกวนนั้นสูงมาก ดังนั้นจึงไม่มีเหตุผลที่จะไม่ใช้มัน

ไม่มีเครื่องมือที่ผิดพลาด หากคุณเขียนconst float pi = 3.14;เครื่องมือส่วนใหญ่จะไม่บอกคุณว่าคุณกำหนดπด้วยความแม่นยำที่ไม่ดีซึ่งอาจนำไปสู่ปัญหาตามมา เครื่องมือส่วนใหญ่จะไม่ยกคิ้วif(tmp < 42)แม้ว่าจะเป็นที่รู้กันดีว่าการตั้งชื่อตัวแปรที่ไม่มีความหมายและการใช้เลขเวทเป็นวิธีหนึ่งที่จะหายนะในโครงการขนาดใหญ่ คุณต้องเข้าใจว่ารหัส "การทดสอบอย่างรวดเร็ว" ที่คุณเขียนนั้นก็คือ: การทดสอบและคุณต้องทำให้ถูกต้องก่อนที่คุณจะย้ายไปทำงานอื่นในขณะที่คุณยังเห็นข้อบกพร่องอยู่ หากคุณปล่อยให้รหัสนั้นเป็นเช่นนั้นการดีบั๊กถ้าหลังจากคุณใช้เวลาสองเดือนในการเพิ่มคุณสมบัติใหม่จะยากขึ้นอย่างมาก

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


3
สำหรับเครื่องมือที่ดีกว่าหรือแย่กว่านั้นclippyเครื่องมือสำหรับผ้าสำลีสำหรับสนิมจริง ๆ จะเตือนเกี่ยวกับค่าคงที่ "3.14" มันเป็นเรื่องจริงเช่นในเอกสาร แต่อย่างที่คุณเดาจากชื่อจงclippyภูมิใจในการเป็นประโยชน์อย่างจริงจัง
emk

1
@emk ขอบคุณสำหรับตัวอย่างนี้บางทีฉันควรใช้ถ้อยคำคำตอบของฉันในไม่เคยพูดว่า "ไม่เคย"ชนิดของวิธีการ ฉันไม่ได้หมายความว่าการตรวจสอบค่า imp ที่ไม่ถูกต้องเป็นไปไม่ได้เพียงแค่การกำจัดคำเตือนเท่านั้นไม่รับประกันคุณภาพของรหัสที่เหมาะสม
Dmitry Grigoryev

สิ่งหนึ่งที่เตือนว่าข้อผิดพลาดจะทำให้คุณได้ว่าการสร้างอัตโนมัติจะล้มเหลวดังนั้นจึงแจ้งเตือนคุณว่ามีบางอย่างผิดพลาด การสร้างอัตโนมัติยังอนุญาตให้ใช้ผ้าสำลีอัตโนมัติ (การระเบิดคือ 3 ... 2 ... 1 .. :)
Móż

8

ในฐานะคนที่ทำงานกับรหัสฝังตัว C แบบดั้งเดิมการเปิดใช้งานคำเตือนคอมไพเลอร์ได้ช่วยแสดงจุดอ่อนและพื้นที่จำนวนมากในการตรวจสอบเมื่อเสนอการแก้ไข ในการใช้ gcc -Wallและ-Wextraและ-Wshadowได้กลายเป็นสิ่งสำคัญ ฉันจะไม่ไปกับอันตรายทุกอย่าง แต่ฉันจะแสดงรายการที่โผล่ขึ้นมาซึ่งช่วยแสดงรหัสปัญหา

ตัวแปรที่ถูกทิ้งไว้ข้างหลัง

สิ่งนี้สามารถชี้ไปที่งานที่ยังไม่เสร็จและพื้นที่ที่อาจไม่สามารถใช้ตัวแปรที่ส่งผ่านทั้งหมดซึ่งอาจเป็นปัญหาได้ ลองดูฟังก์ชั่นง่ายๆที่อาจทำให้เกิดสิ่งนี้:

int foo(int a, int b)
{
   int c = 0;

   if (a > 0)
   {
        return a;
   }
   return 0;
}

เพียงแค่รวบรวมสิ่งนี้โดยไม่มี -Wall หรือ -Wextra ส่งคืนไม่มีปัญหา - จะแจ้งให้คุณทราบแม้ว่าcจะไม่เคยใช้:

foo.c: ในฟังก์ชั่น 'foo':

foo.c: 9: 20: คำเตือน: ตัวแปรที่ไม่ได้ใช้ 'c' [-Wunused-variable]

- Textra จะบอกคุณด้วยว่าพารามิเตอร์ b ของคุณไม่ได้ทำอะไรเลย:

foo.c: ในฟังก์ชั่น 'foo':

foo.c: 9: 20: คำเตือน: ตัวแปรที่ไม่ได้ใช้ 'c' [-Wunused-variable]

foo.c: 7: 20: คำเตือน: พารามิเตอร์ที่ไม่ได้ใช้ 'b' [-Wunused-parameter] int foo (int a, int b)

Global Variable shadowing

หนึ่งบิตนี้ยากและไม่ปรากฏจนกว่าจะ-Wshadowถูกนำมาใช้ ลองปรับเปลี่ยนตัวอย่างด้านบนเพื่อเพิ่ม แต่เกิดขึ้นเป็นโลกที่มีชื่อเดียวกันกับท้องถิ่นซึ่งทำให้เกิดความสับสนมากเมื่อพยายามใช้ทั้งสองอย่าง

int c = 7;

int foo(int a, int b)
{
   int c = a + b;
   return c;
}

เมื่อ -Wshadow เปิดใช้งานมันจะเห็นปัญหานี้ได้ง่าย

foo.c: 11: 9: คำเตือน: การประกาศ 'c' เงาการประกาศทั่วโลก [-Wshadow]

foo.c: 1: 5: หมายเหตุ: การประกาศที่มีเงาอยู่ที่นี่

จัดรูปแบบสตริง

สิ่งนี้ไม่จำเป็นต้องมีการตั้งค่าสถานะพิเศษเป็น gcc แต่มันยังคงเป็นต้นเหตุของปัญหาในอดีต ฟังก์ชั่นง่าย ๆ ที่พยายามพิมพ์ข้อมูล แต่มีข้อผิดพลาดในการจัดรูปแบบอาจมีลักษณะเช่นนี้:

void foo(const char * str)
{
    printf("str = %d\n", str);
}

สิ่งนี้จะไม่พิมพ์สตริงเนื่องจากการจัดรูปแบบธงผิดและ gcc จะบอกคุณอย่างมีความสุขว่านี่อาจไม่ใช่สิ่งที่คุณต้องการ:

foo.c: ในฟังก์ชั่น 'foo':

foo.c: 10: 12: คำเตือน: รูปแบบ '% d' คาดว่าจะโต้แย้งประเภท 'int' แต่ข้อโต้แย้งที่ 2 มีประเภท 'const char *' [-Wformat =]


นี่เป็นเพียงสามสิ่งที่คอมไพเลอร์สามารถตรวจสอบได้อีกครั้งสำหรับคุณ มีคนอื่นอีกหลายคนที่ชอบใช้ตัวแปรที่ไม่ได้กำหนดค่าเริ่มต้นที่คนอื่น ๆ ได้ชี้ให้เห็น


7
ในโลกที่ฝังคำเตือนที่ทำให้ฉันกังวลมากที่สุดคือคำเตือน " possible loss of precision" และ " comparison between signed and unsigned" ฉันพบว่ามันยากที่จะเข้าใจว่า "โปรแกรมเมอร์" เพิกเฉยต่อสิ่งเหล่านี้ (ในความเป็นจริงฉันไม่แน่ใจว่าทำไมพวกเขาถึงไม่ใช่ข้อผิดพลาด)
Mawg กล่าวว่าการคืนสถานะโมนิก้า

3
ในกรณีหลัง @Mawg ฉันเชื่อว่าเหตุผลหลักที่ไม่ใช่ข้อผิดพลาดคือผลลัพธ์ของsizeofไม่ได้ลงนาม แต่ประเภทจำนวนเต็มเริ่มต้นมีการลงนาม sizeofประเภทผลsize_tเป็นที่มักจะใช้สำหรับสิ่งที่เกี่ยวข้องกับขนาดชนิดเช่นเช่นการนับการจัดตำแหน่งหรืออาร์เรย์ / ภาชนะบรรจุองค์ประกอบขณะจำนวนเต็มโดยทั่วไปมีความตั้งใจที่จะใช้เป็น " intเว้นแต่มีความจำเป็นเป็นอย่างอื่น" พิจารณาว่ามีคนกี่คนที่ได้รับการสอนให้ใช้intย้ำเหนือตู้คอนเทนเนอร์ของพวกเขา (เทียบintกับsize_t) ทำให้เกิดข้อผิดพลาดจะทำให้ทุกอย่างคร่าวๆ ; P
Justin Time - Reinstate Monica

6

นี่คือคำตอบเฉพาะสำหรับ C และทำไมสิ่งนี้จึงสำคัญต่อ C มากกว่าสิ่งอื่นใด

#include <stdio.h>
int main()
{
   FILE *fp = "some string";
}

รหัสนี้จะรวบรวมพร้อมกับคำเตือน สิ่งที่ควรและเป็นข้อผิดพลาดในภาษาอื่น ๆ บนโลกทุกภาษา (ยกเว้นภาษาแอสเซมบลี) คือคำเตือนใน C. คำเตือนใน C มักจะมีข้อผิดพลาดในการปลอมตัว คำเตือนควรได้รับการแก้ไขไม่ถูกระงับ

ด้วยเราทำเช่นนี้gccgcc -Wall -Werror

นี่ก็เป็นเหตุผลสำหรับความไม่พอใจสูงเกี่ยวกับคำเตือน API ที่ไม่ปลอดภัยของ MS คนส่วนใหญ่การเขียนโปรแกรม C ได้เรียนรู้วิธีที่ยากในการจัดการคำเตือนว่าเป็นข้อผิดพลาดและสิ่งนี้ดูเหมือนว่าไม่ใช่สิ่งเดียวกันและต้องการการแก้ไขที่ไม่ใช่แบบพกพา


5

คำเตือนของคอมไพเลอร์เป็นเพื่อนของคุณ (ไม่ใช่ตะโกนเรียกตัวพิมพ์ใหญ่เพื่อเน้น)

ฉันทำงานกับระบบ Fortran-77 รุ่นเก่า คอมไพเลอร์บอกสิ่งที่มีค่ากับฉัน: อาร์กิวเมนต์ประเภทข้อมูลไม่ตรงกันในการเรียกรูทีนย่อยโดยใช้ตัวแปรโลคัลก่อนที่ค่าจะถูกตั้งเป็นตัวแปรถ้าฉันมีอาร์กิวเมนต์ตัวแปรหรือรูทีนย่อยที่ไม่ได้ใช้ นี่เป็นข้อผิดพลาดเกือบทุกครั้ง

หลีกเลี่ยงการโพสต์ยาว: เมื่อรหัสของฉันรวบรวมได้อย่างสมบูรณ์ 97% จะทำงาน อีกคนที่ฉันทำงานด้วยคอมไพล์โดยปิดคำเตือนทั้งหมดใช้เวลาหลายชั่วโมงหรือหลายวันในดีบักเกอร์จากนั้นขอให้ฉันช่วย ฉันแค่รวบรวมรหัสของเขาโดยมีคำเตือนแล้วบอกเขาว่าจะแก้ไขอะไร


5

คุณควรเปิดใช้งานคำเตือนคอมไพเลอร์เสมอเพราะคอมไพเลอร์สามารถบอกได้ว่ามีอะไรผิดปกติกับรหัสของคุณ เมื่อต้องการทำเช่นนี้คุณผ่าน-Wall -Wextraจะไปยังคอมไพเลอร์

คุณควรปฏิบัติต่อคำเตือนเป็นข้อผิดพลาดเนื่องจากคำเตือนมักจะมีความหมายว่ามีบางอย่างผิดปกติกับรหัสของคุณ อย่างไรก็ตามมักจะง่ายที่จะละเว้นข้อผิดพลาดเหล่านี้ ดังนั้นการถือว่าพวกเขาเป็นข้อผิดพลาดจะทำให้การสร้างล้มเหลวดังนั้นคุณจึงไม่สามารถละเลยข้อผิดพลาดได้ ในการจัดการกับคำเตือนว่าเป็นข้อผิดพลาดให้ส่ง-Werrorไปยังคอมไพเลอร์


4

คำเตือนคอมไพเลอร์ใน C ++ มีประโยชน์มากด้วยเหตุผลบางประการ

1 - อนุญาตให้แสดงตำแหน่งที่คุณสามารถทำผิดที่สามารถส่งผลต่อผลลัพธ์สุดท้ายของการดำเนินการของคุณ ตัวอย่างเช่นถ้าคุณไม่ได้เริ่มต้นตัวแปรหรือถ้าคุณใส่ "=" แทน "==" (มีเพียงตัวอย่าง)

2 - อนุญาตให้แสดงรหัสของคุณที่ไม่สอดคล้องกับมาตรฐานของ c ++ มันมีประโยชน์เพราะถ้ารหัสนั้นเป็นไปตามมาตรฐานจริงมันจะง่ายต่อการย้ายรหัสไปยัง plateform อื่น ๆ เช่น

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


4

การเพิกเฉยต่อคำเตือนหมายถึงคุณทิ้งโค้ดเลอะเทอะซึ่งไม่เพียง แต่จะทำให้เกิดปัญหากับคนอื่นในอนาคต แต่ยังจะทำให้ข้อความที่สำคัญในการคอมไพล์สังเกตเห็นได้น้อยลง คอมไพเลอร์เอาท์พุทที่มากขึ้นทุกคนที่น้อยลงจะสังเกตเห็นหรือรำคาญ ทำความสะอาดดีกว่า นอกจากนี้ยังหมายความว่าคุณรู้ว่าคุณกำลังทำอะไรอยู่ คำเตือนไม่เป็นมืออาชีพประมาทและเสี่ยง


4

ฉันเคยทำงานให้กับ บริษัท ขนาดใหญ่ (Fortune 50) ที่ผลิตอุปกรณ์ทดสอบอิเล็กทรอนิกส์

ผลิตภัณฑ์หลักของกลุ่มของฉันคือโปรแกรม MFC ที่ในช่วงหลายปีที่ผ่านมาเพื่อสร้างคำเตือนหลายร้อยตัว ซึ่งถูกเพิกเฉยในเกือบทุกกรณี

นี่คือฝันร้าย frigging เมื่อข้อบกพร่องเกิดขึ้น

หลังจากตำแหน่งนั้นฉันโชคดีที่ได้รับการว่าจ้างให้เป็นผู้พัฒนารายแรกในการเริ่มต้นใหม่

ฉันสนับสนุนนโยบาย 'ไม่มีคำเตือน' สำหรับการสร้างทั้งหมดโดยมีระดับคำเตือนคอมไพเลอร์ตั้งเป็นเสียงดัง

การปฏิบัติของเราคือการใช้คำเตือน #pragma - กด / ปิดการใช้งาน / ป๊อปอัพสำหรับรหัสที่นักพัฒนาแน่ใจว่าใช้ได้จริงพร้อมด้วยคำสั่งบันทึกที่ระดับการดีบักในกรณีนี้

วิธีนี้ใช้ได้ผลดีสำหรับเรา


1
หนุน #pragma warningไม่เพียง แต่ยับยั้งคำเตือนเท่านั้นมันมีจุดประสงค์สองอย่างในการสื่อสารกับโปรแกรมเมอร์อื่น ๆ อย่างรวดเร็วว่าสิ่งที่ตั้งใจและไม่ตั้งใจและทำหน้าที่เป็นแท็กการค้นหาเพื่อค้นหาพื้นที่ที่อาจเป็นปัญหาได้อย่างรวดเร็วเมื่อมีบางสิ่งผิดพลาด ซ่อมมัน.
Justin Time - Reinstate Monica

คุณพูดถูกจัสตินนั่นคือวิธีที่ฉันดู #pragma warning
Jim In Texas

3

คำเตือนคือข้อผิดพลาดที่รอให้เกิดขึ้น ดังนั้นคุณต้องเปิดใช้งานคำเตือนคอมไพเลอร์และจัดระเบียบโค้ดของคุณเพื่อลบคำเตือนใด ๆ


3

มีเพียงเป็นหนึ่งในปัญหาเกี่ยวกับการรักษาคำเตือนเป็นข้อผิดพลาด: เมื่อคุณใช้โค้ดมาจากแหล่งอื่น ๆ (เช่นไมโคร $ ** ห้องสมุด T, โครงการโอเพ่นซอร์ส) พวกเขาไม่ได้ทำขวางานของพวกเขาและการรวบรวมรหัสของพวกเขาสร้างตันจากคำเตือน

ฉันมักจะเขียนรหัสของฉันเพื่อที่จะไม่สร้างคำเตือนหรือข้อผิดพลาดใด ๆ และทำความสะอาดมันจนกว่าจะรวบรวมโดยไม่สร้างเสียงรบกวนภายนอกใด ๆ ขยะฉันต้องทำงานกับ appalls ฉันและฉันประหลาดใจเมื่อฉันต้องสร้างโครงการขนาดใหญ่และดูกระแสของคำเตือนไปที่การรวบรวมควรจะประกาศไฟล์ที่ประมวลผลเท่านั้น

ฉันยังบันทึกรหัสของฉันเพราะฉันรู้ว่าค่าใช้จ่ายตลอดอายุการใช้งานจริงของซอฟต์แวร์ส่วนใหญ่มาจากการบำรุงรักษาไม่ใช่จากการเขียนในตอนแรก แต่นั่นเป็นเรื่องที่แตกต่าง ...


อย่าเคาะมันมีเงินที่ดีในการทำงานให้คำปรึกษาสำหรับผู้ที่สามารถอ่านคำเตือนคอมไพเลอร์เสียงดังออกมาให้กับลูกค้า
Móż

ไม่จำเป็นต้องใช้รหัสจากแหล่งอื่นที่สร้างคำเตือนหมายความว่าผู้เขียนเลอะเทอะ อาจหมายถึงว่าพวกเขารวบรวมรหัสด้วยคอมไพเลอร์ที่แตกต่างกันซึ่งสร้างชุดคำเตือนที่แตกต่างกัน รหัสสามารถรวบรวมโดยไม่มีคำเตือนในคอมไพเลอร์หนึ่งและสร้างคำเตือนในอีก หรืออาจเป็นเพียงตัวเลือกการเตือนที่แตกต่างกัน เช่นที่พวกเขาใช้และคุณใช้-Wall -Wall -Wextra
celtschk

2

คำเตือนบางอย่างอาจหมายถึงข้อผิดพลาดทางความหมายที่เป็นไปได้ในรหัสหรือ UB ที่เป็นไปได้ เช่น;หลังจากif()นั้นตัวแปรที่ไม่ได้ใช้ตัวแปรส่วนกลางถูกปิดบังโดยโลคัลหรือการเปรียบเทียบของที่ลงชื่อและไม่ได้ลงนาม คำเตือนจำนวนมากเกี่ยวข้องกับเครื่องวิเคราะห์รหัสแบบคงที่ในคอมไพเลอร์หรือการละเมิดมาตรฐาน ISO ที่ตรวจพบได้ในเวลารวบรวมซึ่ง "ต้องการการวินิจฉัย" ในขณะที่เหตุการณ์เหล่านั้นอาจถูกกฎหมายในบางกรณีพวกเขาจะเป็นผลมาจากปัญหาการออกแบบส่วนใหญ่

คอมไพเลอร์บางตัวเช่น gcc มีตัวเลือกบรรทัดคำสั่งเพื่อเปิดใช้งานโหมด "คำเตือนเป็นข้อผิดพลาด" มันดีถ้าเครื่องมือที่โหดร้ายเพื่อให้ความรู้แก่ผู้เริ่มหัดใช้มือใหม่


1

ความจริงที่ว่าคอมไพเลอร์ C ++ ยอมรับการคอมไพล์โค้ดที่เห็นได้ชัดว่ามีพฤติกรรมที่ไม่ได้กำหนดเลยเป็นข้อบกพร่องที่สำคัญในคอมไพเลอร์ เหตุผลที่พวกเขาไม่แก้ไขปัญหานี้ก็เพราะการทำเช่นนั้นอาจทำให้งานสร้างที่ใช้งานไม่ได้บางส่วน

คำเตือนส่วนใหญ่ควรเป็นข้อผิดพลาดร้ายแรงที่ทำให้การสร้างไม่เสร็จสมบูรณ์ ค่าเริ่มต้นสำหรับเพียงแสดงข้อผิดพลาดและสร้างส่วนต่อไปนั้นผิดและถ้าคุณไม่แทนที่พวกเขาเพื่อจัดการกับคำเตือนเป็นข้อผิดพลาดและออกจากคำเตือนบางอย่างคุณอาจจะจบลงด้วยโปรแกรมของคุณทำงานล้มเหลวและทำสิ่งต่าง ๆ แบบสุ่ม


พฤติกรรมที่ไม่ได้กำหนดจำนวนมากไม่ได้ก่อให้เกิดการเตือน แต่ก็รวบรวมได้อย่างเงียบ ๆ ในการวางระเบิดครั้งเล็กน้อยที่น่ารังเกียจ ; P
Justin Time - Reinstate Monica

1
ปัญหาคือว่าหากมาตรฐานต้องการข้อความแสดงข้อผิดพลาดข้อความข้อผิดพลาดนั้นจะต้องออกในทุกกรณีที่เกิดปัญหา แต่จะไม่เกิดขึ้นหากปัญหาไม่เกิดขึ้น แต่ในกรณีเช่นพฤติกรรมที่ไม่ได้กำหนดอาจเป็นไปไม่ได้ที่จะตัดสินใจ ตัวอย่างเช่นพิจารณารหัสต่อไปนี้: รหัสint i; if (fun1()) i=2; if (fun2()) i=3; char s="abcde"[i];นี้แสดงพฤติกรรมที่ไม่ได้กำหนดถ้าหากทั้งคู่fun1()และfun2()สามารถกลับมาfalseในการทำงานของฟังก์ชั่นเดียวกัน สิ่งใดที่อาจจริงหรือไม่จริง แต่คอมไพเลอร์จะบอกอย่างไร?
celtschk

-2

คุณควรเปิดใช้งานคำเตือนคอมไพเลอร์อย่างแน่นอนเนื่องจากคอมไพเลอร์บางตัวไม่ดีในการรายงานข้อผิดพลาดทั่วไปของการเขียนโปรแกรมรวมถึงสิ่งต่อไปนี้: -

-> กำหนดค่าเริ่มต้นให้กับตัวแปรที่ถูกลืม -> ส่งคืนค่าจากฟังก์ชันที่พลาด -> อาร์กิวเมนต์ง่าย ๆ ในตระกูล printf และ scanf ที่ไม่ตรงกับสตริงรูปแบบที่ฟังก์ชันใช้โดยไม่ต้องประกาศล่วงหน้าแม้ว่าจะเกิดขึ้นใน c เท่านั้น

ดังนั้นในขณะที่ฟังก์ชั่นเหล่านี้สามารถตรวจจับและรายงานได้โดยปกติแล้วจะไม่ใช่ตามค่าเริ่มต้น ดังนั้นคุณสมบัตินี้จะต้องได้รับการร้องขออย่างชัดเจนผ่านตัวเลือกคอมไพเลอร์


-32

ใช้ง่าย: คุณไม่ต้องทำก็ไม่จำเป็น -Wall และ -Werror รับการออกแบบโดยบ้ารหัส refactoring สำหรับตัวเอง: มันถูกคิดค้นโดยนักพัฒนาคอมไพเลอร์ที่จะหลีกเลี่ยงการทำลายที่มีอยู่สร้างหลังจากการปรับปรุงคอมไพเลอร์ในด้านการใช้ คุณลักษณะไม่มีอะไร แต่ทั้งหมดเกี่ยวกับการตัดสินใจที่จะทำลายหรือไม่ทำลายการสร้าง

มันขึ้นอยู่กับความชอบของคุณที่จะใช้หรือไม่ ฉันใช้มันตลอดเวลาเพราะมันช่วยให้ฉันแก้ไขข้อผิดพลาดได้


19
แม้ว่าจะไม่ได้รับคำแนะนำแต่ก็ขอแนะนำให้ใช้พวกเขา
Spikatrix

18
-Wall and -Werror was designed by code-refactoring maniacs for themselves.[จำเป็น]
YSC

22
ดูเหมือนว่าคุณจะขัดแย้งกับตัวเอง ถ้าคุณ "ใช้มันตลอดเวลาเพราะมันช่วยในการแก้ไขข้อผิดพลาด [ของคุณ]" มันไม่คุ้มค่าที่จะสอนให้โปรแกรมเมอร์รุ่นใหม่ ๆ ฉันไม่คิดว่าคำถามนี้ถามว่าจะเป็นไปได้หรือไม่ที่จะรวบรวมได้-Wallและ-Werrorเป็นเพียงการถามว่าเป็นความคิดที่ดีหรือไม่ ซึ่งจากประโยคสุดท้ายของคุณดูเหมือนว่าคุณกำลังพูดว่า
scohe001

12
เมื่อคุณได้รับประสบการณ์มากขึ้นกับการบำรุงรักษาโค้ดที่คุณไม่ได้เขียนให้กลับมาตอบคำถามนี้
Thorbjørn Ravn Andersen

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