อ่าน 2 นาที
ความปลอดภัยที่เป็นข้อยกเว้น
ความปลอดภัยของข้อยกเว้นคือสถานะของโค้ดที่ทำงานได้อย่างถูกต้องเมื่อมีการโยนข้อยกเว้นเพื่อช่วยให้มั่นใจในความปลอดภัยของข้อยกเว้น นักพัฒนาไลบรารีมาตรฐาน...
ความปลอดภัยที่เป็นข้อยกเว้น
ความปลอดภัยของข้อยกเว้นคือสถานะของโค้ดที่ทำงานได้อย่างถูกต้องเมื่อมีการโยนข้อยกเว้น[ 1 ]เพื่อช่วยให้มั่นใจในความปลอดภัยของข้อยกเว้น นักพัฒนาไลบรารีมาตรฐาน C++ได้คิดค้นชุดระดับความปลอดภัยของข้อยกเว้น ซึ่งเป็นการรับประกันตามสัญญาเกี่ยวกับพฤติกรรมของการดำเนินการของโครงสร้างข้อมูลที่เกี่ยวข้องกับข้อยกเว้น ผู้พัฒนาไลบรารีและลูกค้าสามารถใช้การรับประกันเหล่านี้เมื่อพิจารณาถึง ความถูกต้อง ของการจัดการข้อยกเว้นระดับความปลอดภัยของข้อยกเว้นใช้ได้กับภาษาอื่นๆ และกลไกการจัดการข้อผิดพลาดเช่นกัน[ 2 ]
ประวัติศาสตร์
ดังที่David Abrahamsเขียนไว้ว่า "ไม่มีใครเคยพูดถึง 'ความปลอดภัยจากข้อผิดพลาด' มาก่อนที่ C++ จะมีข้อยกเว้น" [ 3 ] คำนี้ปรากฏเป็นหัวข้อของเอกสารเผยแพร่ในJTC1/SC22/WG21ซึ่งเป็นคณะกรรมการมาตรฐาน C++ ตั้งแต่ปี 1994 [ 4 ]ความปลอดภัยของข้อยกเว้นสำหรับไลบรารีมาตรฐาน C++ ได้รับการกำหนดอย่างเป็นทางการครั้งแรกสำหรับSTLportโดย Abrahams ซึ่งได้กำหนดความแตกต่างระหว่างความปลอดภัยพื้นฐานและความปลอดภัยที่เข้มงวด[ 5 ]สิ่งนี้ได้รับการขยายไปสู่การรับประกันพื้นฐาน/เข้มงวด/ไม่โยนข้อยกเว้นที่ทันสมัยในข้อเสนอในภายหลัง[ 6 ]
พื้นหลัง
ข้อยกเว้นเป็นรูปแบบหนึ่งของ การควบคุมการไหลที่ไม่ใช่แบบโลคอลเนื่องจากข้อยกเว้นอาจ "แพร่กระจาย" ขึ้นจากฟังก์ชันที่ถูกเรียก การแพร่กระจายนี้อาจทำให้เกิดข้อบกพร่องด้านความปลอดภัยของข้อยกเว้นโดยการทำลายความไม่เปลี่ยนแปลงของโครงสร้างข้อมูลที่เปลี่ยนแปลงได้ ดังต่อไปนี้: [ 7 ]
- ขั้นตอนหนึ่งของการดำเนินการกับโครงสร้างข้อมูลที่เปลี่ยนแปลงได้จะแก้ไขข้อมูลและทำลายคุณสมบัติคงที่ของข้อมูล
- เกิดข้อผิดพลาดขึ้น และการควบคุมจะ "ส่งต่อไปยังระดับที่สูงขึ้น" โดยข้ามส่วนที่เหลือของโค้ดการทำงานที่ทำหน้าที่คืนค่าสถานะคงที่
- ข้อผิดพลาดถูกตรวจจับและกู้คืน หรือ
finallyมีการเข้าสู่บล็อก - โครงสร้างข้อมูลที่มีเงื่อนไขคงที่ที่เสียหายถูกนำไปใช้โดยโค้ดที่ถือว่าเงื่อนไขคงที่นั้นถูกต้อง ส่งผลให้เกิดข้อผิดพลาด
โค้ดที่มีบั๊กดังที่กล่าวมาข้างต้นอาจกล่าวได้ว่า "ไม่ปลอดภัยต่อข้อยกเว้น" [ 7 ]
การจำแนกประเภท
ไลบรารีมาตรฐาน C++มีระดับความปลอดภัยของข้อยกเว้นหลายระดับ (เรียงลำดับจากความปลอดภัยมากที่สุดไปน้อยที่สุด): [ 8 ]
- รับประกันความสำเร็จโดยไม่ผิดพลาดหรือที่เรียกว่าความโปร่งใสของความล้มเหลว : การดำเนินงานได้รับการรับประกันว่าจะประสบความสำเร็จและตรงตามข้อกำหนดทั้งหมด แม้ในสถานการณ์พิเศษ หากเกิดข้อผิดพลาดขึ้น จะได้รับการจัดการภายในและลูกค้าจะไม่พบเห็น
- ความปลอดภัยของข้อยกเว้นที่แข็งแกร่งหรือที่รู้จักกันในชื่อความหมายของการยืนยันหรือการยกเลิก : การดำเนินการอาจล้มเหลว แต่การดำเนินการที่ล้มเหลวรับประกันว่าจะไม่มีผลข้างเคียง ทำให้ค่าเดิมยังคงอยู่[ 9 ]
- ความปลอดภัยของข้อยกเว้นขั้นพื้นฐาน : การดำเนินการบางส่วนของกระบวนการที่ล้มเหลวอาจส่งผลให้เกิดผลข้างเคียง แต่เงื่อนไขพื้นฐาน ทั้งหมด จะยังคงอยู่ ข้อมูลที่จัดเก็บไว้จะมีค่าที่ถูกต้อง ซึ่งอาจแตกต่างจากค่าเดิมการรั่วไหลของทรัพยากร (รวมถึงการรั่วไหลของหน่วยความจำ ) มักจะถูกตัดออกไปโดยเงื่อนไขพื้นฐานที่ระบุว่าทรัพยากรทั้งหมดได้รับการตรวจสอบและจัดการแล้ว
- ไม่มีข้อยกเว้นด้านความปลอดภัย : ไม่มีการรับประกันใดๆ ทั้งสิ้น
โดยทั่วไปแล้ว การเขียนโค้ดที่แข็งแกร่งนั้นจำเป็นต้องมีระบบรักษาความปลอดภัยจากข้อยกเว้นขั้นพื้นฐานเป็นอย่างน้อย การรักษาความปลอดภัยในระดับที่สูงขึ้นอาจทำได้ยาก และอาจทำให้เกิดภาระเพิ่มเติมเนื่องจากการคัดลอกข้อมูลมากขึ้น กลไกสำคัญสำหรับการรักษาความปลอดภัยจากข้อยกเว้นคือfinallyข้อความ `dispose` หรือไวยากรณ์การจัดการข้อยกเว้น ที่คล้ายกัน ซึ่งช่วยให้มั่นใจได้ว่าโค้ดบางส่วนจะ ทำงาน เสมอเมื่อออกจากบล็อก รวมถึงกรณีที่มีข้อยกเว้นด้วย ภาษาโปรแกรมหลายภาษามีโครงสร้างที่ทำให้เรื่องนี้ง่ายขึ้น โดยเฉพาะอย่างยิ่งการใช้รูปแบบ `dispose`ซึ่งเรียกว่า ` dispose` using, `dispose.json` withหรือtry`dispose.json` ที่มีทรัพยากร
ตัวอย่าง
ลองพิจารณาประเภทเวกเตอร์อัจฉริยะ เช่น เวกเตอร์ในภาษา C++ หรือ Java เมื่อมีการเพิ่มรายการลงในเวกเตอร์เวกเตอร์จะต้องเพิ่ม รายการ นั้นลงในลิสต์ภายในของวัตถุและอัปเดตฟิลด์นับจำนวนที่ระบุว่ามีวัตถุอยู่กี่ชิ้นนอกจากนี้ อาจจำเป็นต้องจัดสรรหน่วยความจำใหม่หากความจุที่มีอยู่ไม่เพียงพอ std::vectorArrayListxvxv
ทางเลือกด้านความปลอดภัยที่เป็นข้อยกเว้น:
- รับประกันไม่โยนทิ้ง
- สามารถนำไปใช้ได้โดยการรับประกันว่าการจัดสรรหน่วยความจำจะไม่ล้มเหลว หรือโดยการกำหนด
insertพฤติกรรมของฟังก์ชันเมื่อการจัดสรรล้มเหลว (ตัวอย่างเช่น โดยให้ฟังก์ชันส่งคืนค่าบูลีนที่ระบุว่าการแทรกเกิดขึ้นหรือไม่) - ความปลอดภัยข้อยกเว้นที่แข็งแกร่ง
- วิธีการนี้ใช้หลักการจัดสรรพื้นที่ก่อน จากนั้นจึงสลับบัฟเฟอร์หากไม่พบข้อผิดพลาด (ซึ่ง เป็นวิธี การคัดลอกและสลับ ) ในกรณีนี้ การแทรกข้อมูล
xลงไปvจะสำเร็จ หรือvข้อมูลจะยังคงไม่เปลี่ยนแปลงแม้ว่าการจัดสรรพื้นที่จะล้มเหลวก็ตาม - ความปลอดภัยข้อยกเว้นขั้นพื้นฐาน
- วิธีการนี้ดำเนินการโดยการรับประกันว่าฟิลด์จำนวนนับจะสะท้อนขนาดสุดท้ายของออบเจ็ก
vต์อย่างแน่นอน ตัวอย่างเช่น หากพบข้อผิดพลาดinsertฟังก์ชันอาจยกเลิกการจัดสรรหน่วยความจำทั้งหมดvและรีเซ็ตฟิลด์จำนวนนับเป็นศูนย์ ในกรณีที่ล้มเหลว จะไม่มีการรั่วไหลของทรัพยากร แต่vค่าเดิมของออบเจ็กต์จะไม่ถูกเก็บรักษาไว้ - ไม่มีข้อยกเว้นด้านความปลอดภัย
- ความล้มเหลวในการแทรกข้อมูลอาจนำไปสู่เนื้อหาที่เสียหาย
vค่าที่ไม่ถูกต้องในฟิลด์จำนวน หรือ การรั่ว ไหลของทรัพยากร
ลิงก์ภายนอก
- เฮิร์บ ซัตเตอร์: C++ ที่ยอดเยี่ยม: 47 ปริศนาทางวิศวกรรม ปัญหาการเขียนโปรแกรม และวิธีแก้ปัญหา, ปี 2000
- Jon Kalb: การเขียนโค้ด C++ ที่ปลอดภัยจากข้อยกเว้นพร้อมด้วยการนำเสนอเรื่องความปลอดภัยจากข้อยกเว้นในงาน C++Now! 2012
- หัวข้อสนทนาที่เกี่ยวข้องบน Stackoverflow: C++: คุณเขียนโค้ดที่ปลอดภัยจากข้อผิดพลาด (จริงๆ) หรือไม่
สรุปเนื้อหา
ข้อมูลสำคัญจากบทความ
ข้อมูลสำคัญเกี่ยวกับ ความปลอดภัยที่เป็นข้อยกเว้น
ความปลอดภัยของข้อยกเว้นคือสถานะของโค้ดที่ทำงานได้อย่างถูกต้องเมื่อมีการโยนข้อยกเว้นเพื่อช่วยให้มั่นใจในความปลอดภัยของข้อยกเว้น นักพัฒนาไลบรารีมาตรฐาน...
ประวัติศาสตร์
ดังที่ David Abrahams เขียนไว้ว่า "ไม่มีใครเคยพูดถึง 'ความปลอดภัยจากข้อผิดพลาด' มาก่อนที่ C++ จะมีข้อยกเว้น" [ 3 ] คำนี้ปรากฏเป็นหัวข้อของเอกสารเผยแพร่ใน JTC1/SC22/WG21 ซึ่งเป็นคณะกรรมการมาตรฐาน C++ ตั้งแต่ปี 1994 [ 4 ]...
พื้นหลัง
ข้อยกเว้นเป็นรูปแบบหนึ่งของ การควบคุมการไหล ที่ไม่ใช่แบบโลคอลเนื่องจากข้อยกเว้นอาจ "แพร่กระจาย" ขึ้นจากฟังก์ชันที่ถูกเรียก การแพร่กระจายนี้อาจทำให้เกิดข้อบกพร่องด้านความปลอดภัยของข้อยกเว้นโดยการทำลายความไม่เปลี่ยนแปลงของโครงสร้างข้อมูลที่เปลี่ยนแปลงได้...
การจำแนกประเภท
ไลบรารี มาตรฐาน C++ มีระดับความปลอดภัยของข้อยกเว้นหลายระดับ (เรียงลำดับจากความปลอดภัยมากที่สุดไปน้อยที่สุด): [ 8 ]