ภาษาโปรแกรมที่ปลอดภัยคืออะไร


55

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


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Gilles 'หยุดความชั่วร้าย'

"เราสามารถใช้ชุดย่อยที่ปลอดภัยได้ตลอดเวลา"คุณจะแน่ใจได้อย่างไรว่าภาษาที่ได้นั้นยังคงเป็นทัวริงอยู่ (ซึ่งเป็นสิ่งที่มักจะหมายถึง "การเขียนโปรแกรมภาษา")
EFFEFFE

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

คำตอบ:


17

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

สิ่งสำคัญบางประการคือ:

  • Andrew Wright และ Matthias Felleisen ได้นิยามคำว่า "ความสมบูรณ์แบบ"ซึ่งมีการกล่าวถึงในหลาย ๆ ที่ (รวมถึง Wikipedia) ในฐานะที่เป็นคำนิยามที่ยอมรับได้ของ "ความปลอดภัยของประเภท" และหลักฐานปี 1994 ของพวกเขาว่า

  • ไมเคิลฮิกส์หลายรายการคำนิยามของ“ความปลอดภัยความทรงจำ” ที่นี่ บางรายการเป็นประเภทของข้อผิดพลาดที่ไม่สามารถเกิดขึ้นได้และบางรายการขึ้นอยู่กับการรักษาพอยน์เตอร์เป็นความสามารถ Java รับประกันว่าไม่มีข้อผิดพลาดใด ๆ ที่เป็นไปได้ (เว้นแต่คุณจะใช้คุณลักษณะที่ทำเครื่องหมายไว้อย่างชัดเจนunsafe) โดยให้ตัวรวบรวมขยะจัดการการจัดสรรและการจัดสรรคืนทั้งหมด สนิมทำให้การรับประกันเดียวกัน (อีกครั้งยกเว้นว่าคุณทำเครื่องหมายรหัสไว้อย่างชัดเจนunsafe) ผ่านระบบประเภทเลียนแบบซึ่งต้องการตัวแปรที่จะเป็นเจ้าของหรือยืมก่อนที่จะถูกใช้อย่างมากที่สุดครั้งเดียว

  • ในทำนองเดียวกันรหัสปลอดภัยของเธรดมักจะถูกกำหนดเป็นรหัสที่ไม่สามารถแสดงข้อบกพร่องบางประเภทที่เกี่ยวข้องกับเธรดและหน่วยความจำที่ใช้ร่วมกันรวมถึงการแย่งชิงข้อมูลและการหยุดชะงัก คุณสมบัติเหล่านี้มักจะมีการบังคับใช้ในระดับภาษา: สนิมรับประกันได้ว่าข้อมูลการแข่งขันไม่สามารถเกิดขึ้นได้ในระบบประเภทของมัน C ++ รับประกันได้ว่าstd::shared_ptrสมาร์ทพอยน์เตอร์ไปยังวัตถุเดียวกันในหลายเธรดจะไม่ลบวัตถุก่อนกำหนดหรือล้มเหลว จะถูกทำลาย, C และ C ++ นอกจากนี้ยังมีatomicตัวแปรที่สร้างขึ้นในภาษาที่มีการดำเนินการปรมาณูรับประกันว่าจะบังคับใช้ความสอดคล้องหน่วยความจำบางชนิดถ้าใช้อย่างถูกต้อง MPI จำกัด การสื่อสารระหว่างกระบวนการกับข้อความที่ชัดเจนและ OpenMP มีไวยากรณ์เพื่อให้แน่ใจว่าการเข้าถึงตัวแปรจากเธรดที่แตกต่างนั้นปลอดภัย

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

  • หลายภาษามีการรับประกันว่าการทำงานของมันจะมีผลลัพธ์ที่ชัดเจนและโปรแกรมของมันจะมีความประพฤติดี ในฐานะที่เป็นตัวอย่างของซูเปอร์แคทข้างต้น C ทำสิ่งนี้สำหรับเลขคณิตที่ไม่ได้ลงนาม (รับประกันการห่อรอบอย่างปลอดภัย) แต่ไม่ได้ลงนามทางคณิตศาสตร์ (ที่ล้นได้รับอนุญาตให้ก่อให้เกิดข้อผิดพลาดโดยพลการเพราะ C จำเป็นต้องสนับสนุน CPU มากเกิน) แต่บางครั้งภาษาก็จะแปลงปริมาณที่ไม่ได้รับการรับรองให้กลายเป็นสิ่งที่ถูกลงชื่อ

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

  • บางภาษาเช่น SPARK หรือ OCaml ได้รับการออกแบบมาเพื่ออำนวยความสะดวกในการพิสูจน์ความถูกต้องของโปรแกรม สิ่งนี้อาจหรืออาจจะไม่ได้อธิบายว่าเป็น "ปลอดภัย" จากข้อบกพร่อง

  • พิสูจน์ว่าระบบไม่สามารถละเมิดรูปแบบการรักษาความปลอดภัยที่เป็นทางการได้ (เช่นคำว่า "ระบบใด ๆ ที่พิสูจน์ได้ว่ามีความปลอดภัยอาจไม่ใช่")


1
สิ่งนี้อาจหรืออาจจะไม่ได้อธิบายว่าเป็น "ปลอดภัย" จากข้อบกพร่อง คุณช่วยอธิบายเรื่องนี้หน่อยได้ไหม? คุณหมายถึงอะไร "จากบั๊ก"
scaaahu

2
@scaaahu ต่อไปนี้เป็นตัวอย่างของเว็บไซต์ที่อ้างถึงซอฟต์แวร์ที่ได้รับการพิสูจน์อย่างเป็นทางการว่า "ปลอดภัยอย่างยิ่ง" ในบริบทนี้หมายถึงซอฟต์แวร์เพื่อป้องกันไม่ให้เครื่องบินชนกันดังนั้นจึงปลอดภัยจากการชน
Davislor

1
ฉันยอมรับคำตอบนี้เพราะมันแสดงประเภทของความปลอดภัย ประเภทที่ฉันมีในใจคือความปลอดภัยของหน่วยความจำ
beroal

ในขณะที่คำตอบนี้แสดงลิงค์ที่มีประโยชน์และตัวอย่างมากมาย แต่ส่วนใหญ่ลิงก์เหล่านั้นจะสับสนอย่างสมบูรณ์ การรวบรวมขยะทำให้มั่นใจได้ว่าหน่วยความจำจะไม่รั่วไหลหรือไม่ใช้บล็อก "ไม่ปลอดภัย" โดยอัตโนมัติช่วยให้คุณปลอดภัยหรือมีการลงชื่อล้นหลามเป็นพฤติกรรมที่ไม่ได้กำหนดเนื่องจากคอมไพเลอร์Сต้องสนับสนุนซีพียูแปลก ๆ หรือไม่? และเป็นเพียงคำศัพท์สั้น ๆ สำหรับ Ada / SPARK ซึ่งเป็นภาษาเดียวเท่านั้นที่พูดถึงเรื่องความปลอดภัยอย่างจริงจัง
VTT

94

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


13
ในฐานะที่เป็น addeumdum ถ้าเราพูดถึง C vs Java เหมือนกับการโพสต์ของ OP: มันเป็นความปลอดภัยของหน่วยความจำที่รับประกันใน Java และไม่ได้อยู่ใน C. ความปลอดภัยของประเภทนั้นมีให้ทั้งในทางของตัวเอง (ใช่คนจำนวนมากที่อ่านข้อความนี้รู้อยู่แล้ว แต่อาจมีบางคนไม่เห็น)
Walfrat

17
@ Walrat นั่นเป็นส่วนหนึ่งของมัน Java ยังไม่มีพฤติกรรมที่ไม่ได้กำหนดซึ่งเป็นสิ่งที่เราคาดหวังจากภาษาที่เรียกตัวเองว่า 'ปลอดภัย' สำหรับระบบการพิมพ์ฉันไม่คิดว่าระบบการพิมพ์แบบคงที่ที่แข็งแกร่งคือสิ่งที่ผู้คนมักจะหมายถึงโดย 'ปลอดภัย' ภาษาที่พิมพ์แบบไดนามิกเช่น Python โดยทั่วไปแล้วจะ 'ปลอดภัย'
Max Barraclough

2
คำจำกัดความของความปลอดภัยประเภทของฉันคือการตรวจสอบการรวบรวมที่จัดการ นั่นอาจไม่ใช่คำจำกัดความที่เป็นทางการ โปรดทราบว่าฉันพูดว่า "type safety" ไม่ใช่ "safe" สำหรับฉันภาษา "ปลอดภัย" อ้างอิงถึงคำจำกัดความ "ประเภท" และ "ความปลอดภัยของหน่วยความจำ" ของฉันและฉันคิดว่ามันอาจเป็นภาษาที่แพร่หลายที่สุด แน่นอนฉันไม่ได้พูดถึงหลุมพรางบางอย่างเช่นการสะท้อน / โมฆะตัวชี้ใน C ที่รวบรวมไม่สามารถจัดการ คำจำกัดความที่เป็นไปได้อีกอย่างหนึ่งของความปลอดภัยคือโปรแกรมที่ไม่ผิดพลาดกับข้อผิดพลาดส่วนเช่นตัวชี้หน่วยในซีสิ่งต่างๆที่ได้รับโดยทั่วไปใน Python และ Java
Walfrat

7
@ Walrat ทั้งหมดที่ทำให้คุณได้รับนั้นเป็นภาษาที่มีการกำหนดไวยากรณ์ไว้อย่างดี ไม่รับประกันว่าการประมวลผลจะถูกกำหนดไว้อย่างดี - และจำนวนครั้งที่ฉันเห็น JRE ล้มเหลวฉันสามารถบอกคุณได้ว่าระบบไม่ปลอดภัย "" ในทางกลับกัน MISRA ได้พยายามหลีกเลี่ยงพฤติกรรมที่ไม่ได้กำหนดเพื่อให้ได้เซตย่อยที่ปลอดภัยกว่าของภาษา ดังนั้นมันขึ้นอยู่กับสิ่งที่คุณพิจารณาว่า "ปลอดภัย"
เกรแฮม

5
@MaxBarraclough - "Java ยังไม่มีพฤติกรรมที่ไม่ได้กำหนด" - Java ไม่มีพฤติกรรมที่ไม่ได้กำหนดในแง่ที่ใช้ในข้อกำหนด C ในการกำหนดภาษา (แม้ว่าจะอนุญาตให้บางรหัสผลิตค่าที่ไม่มีค่าที่กำหนดไว้ล่วงหน้าเช่นการเข้าถึง ตัวแปรที่ถูกแก้ไขในเธรดอื่นหรือโดยการเข้าถึงdoubleหรือlongในขณะที่กำลังแก้ไขในเธรดอื่นซึ่งไม่รับประกันว่าจะไม่สร้างครึ่งหนึ่งของค่าหนึ่งที่ผสมในบางวิธีที่ไม่ได้ระบุกับอีกครึ่งหนึ่ง) แต่ข้อมูลจำเพาะ API อย่างไรก็ตามมีพฤติกรรมที่ไม่ได้กำหนดในบางกรณี
จูลส์

42

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

การตีความที่นำเสนอหนึ่งคำที่คุณอาจพบว่าน่าสนใจคือ:

“ ภาษาที่ปลอดภัยถูกกำหนดไว้อย่างสมบูรณ์ในคู่มือของโปรแกรมเมอร์” ให้คำจำกัดความของภาษาเป็นชุดของสิ่งที่โปรแกรมเมอร์ต้องเข้าใจเพื่อทำนายพฤติกรรมของทุกโปรแกรมในภาษา จากนั้นคู่มือสำหรับภาษาอย่าง C ไม่ได้เป็นคำนิยามเนื่องจากพฤติกรรมของบางโปรแกรม (เช่นคนที่เกี่ยวข้องกับการเข้าถึงอาเรย์ที่ไม่ได้ตรวจสอบหรือตัวชี้ทางคณิตศาสตร์) ไม่สามารถทำนายได้โดยไม่ทราบรายละเอียดว่าคอมไพเลอร์ C ฯลฯ และโปรแกรมเดียวกันอาจมีพฤติกรรมที่แตกต่างกันมากเมื่อดำเนินการโดยคอมไพเลอร์ต่างกัน

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


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

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

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

9
@Gilles: ฉันตระหนักดีถึงความจริงที่ว่าหลายโปรแกรมได้รับการพิสูจน์แล้วว่าหยุดหรือไม่ แต่ข้อความที่นี่มีความหมายเกี่ยวกับพฤติกรรมของทุกโปรแกรม การพิสูจน์ทฤษฎีบท Halting แสดงให้เห็นว่ามีโปรแกรมอย่างน้อยหนึ่งรายการที่ไม่เป็นความจริง มันเป็นเพียงหลักฐานที่ไม่สร้างสรรค์ก็จะไม่บอกคุณซึ่งโปรแกรมที่ตัดสินไม่ได้
MSalters

8
@Malters ฉันคิดว่าบิตโดยนัยคือคำสั่งที่เกี่ยวกับพฤติกรรมขนาดเล็กของโปรแกรมมากกว่าพฤติกรรมขนาดใหญ่เกิดขึ้นเร็ว ยกตัวอย่างเช่นการใช้การคาดเดา Collatz แต่ละขั้นตอนของอัลกอริธึมนั้นเรียบง่ายและถูกกำหนดไว้อย่างดี แต่พฤติกรรมฉุกเฉิน (มีกี่ครั้งที่ต้องทำซ้ำจนกว่าจะหยุดและหากมันเกิดขึ้นทั้งหมด) ก็ไม่มีอะไรเกิดขึ้น - "Predict" กำลังถูกใช้อย่างไม่เป็นทางการที่นี่ มันอาจจะดีกว่าเขียนว่า "รู้ว่าคำสั่งใด ๆ ที่ได้รับในโปรแกรมโดยพลการจะดำเนินการ"
RM

18

ปลอดภัยไม่ไบนารีมันเป็นความต่อเนื่อง

การพูดอย่างไม่เป็นทางการความปลอดภัยหมายถึงการต่อต้านข้อบกพร่อง 2 สิ่งที่ถูกกล่าวถึงบ่อยที่สุดคือ:

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

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

เพียงแค่โปรแกรมที่ไม่ถูกต้องมักจะถูกพิจารณาว่าเป็น "ไม่ปลอดภัย" (เป็นบั๊กกี้เท่านั้น) และโดยทั่วไปคำว่าความปลอดภัยนั้นสงวนไว้สำหรับการรับประกันที่ส่งผลต่อความสามารถของเราในการให้เหตุผลเกี่ยวกับโปรแกรม ดังนั้น C, C ++ หรือ Go ที่มีพฤติกรรมที่ไม่ได้กำหนดไม่ปลอดภัย

และแน่นอนว่ายังมีภาษาที่มีชุดย่อยที่ไม่ปลอดภัย (Java, Rust, ... ) ซึ่งแยกส่วนที่ผู้พัฒนามีหน้าที่รับผิดชอบในการรักษาการรับประกันภาษาและคอมไพเลอร์อยู่ในโหมด "hands-off" ภาษายังคงขนานนามโดยทั่วไปว่าปลอดภัยแม้จะมีช่องโหว่นี้เป็นคำจำกัดความที่ใช้งานได้จริง


7
ฉันว่ามันเป็นขัดแตะ
PatJ

1
การใช้ภาษาโปรแกรมส่วนใหญ่มีคุณสมบัติที่ไม่ปลอดภัย (เช่นObj.magicใน Ocaml) และในทางปฏิบัติสิ่งเหล่านี้จำเป็นจริงๆ
Basile Starynkevitch

4
@BasileStarynkevitch: แน่นอน ฉันคิดว่าภาษาใด ๆ ที่มี FFI จำเป็นต้องมีระดับของความไม่ปลอดภัยเนื่องจากการเรียกใช้ฟังก์ชัน C จะต้องใช้วัตถุ "pining" GC'ed และตรวจสอบให้แน่ใจว่าลายเซ็นของทั้งสองฝ่ายตรงกัน
Matthieu M.

15

แม้ว่าฉันจะไม่เห็นด้วยกับคำตอบของ DW แต่ฉันคิดว่ามันเป็นส่วนหนึ่งของ "ปลอดภัย" ที่ไม่ได้รับการแก้ไข

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

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

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


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

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

9

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

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

Modern C ก้าวไปอีกขั้น: แม้ว่าเป้าหมายกำลังกำหนดแพลตฟอร์มซึ่งจะกำหนดพฤติกรรมสำหรับบางอย่างเช่นตัวเลขล้นซึ่งมาตรฐานจะไม่มีข้อกำหนด แต่การล้นในส่วนหนึ่งของโปรแกรมอาจส่งผลกระทบต่อพฤติกรรมของส่วนอื่น ๆ ของ โปรแกรมในลักษณะโดยพลการไม่ผูกพันตามกฎหมายของเวลาและเวรกรรม ตัวอย่างเช่นลองพิจารณาสิ่งต่อไปนี้:

 uint32_t test(uint16_t x)
 {
   if (x < 50000) foo(x);
   return x*x; // Note x will promote to "int" if that type is >16 bits.
 }

คอมไพเลอร์ "modern" C ที่ให้บางอย่างเช่นด้านบนอาจสรุปได้ว่าเนื่องจากการคำนวณของ x * x จะล้นถ้า x มากกว่า 46340 มันสามารถทำการเรียกไปที่ "foo" โดยไม่มีเงื่อนไข โปรดทราบว่าแม้ว่ามันจะเป็นที่ยอมรับได้ที่จะมีโปรแกรมยุติอย่างผิดปกติถ้า x อยู่นอกช่วงหรือฟังก์ชั่นคืนค่าใด ๆ ในกรณีเช่นนี้การเรียก foo () ด้วยการอยู่นอกขอบเขต x อาจทำให้เกิดความเสียหายเกินกว่า ความเป็นไปได้เหล่านั้นอย่างใดอย่างหนึ่ง ดั้งเดิม C จะไม่ให้อุปกรณ์ความปลอดภัยใด ๆ นอกเหนือจากที่โปรแกรมเมอร์และแพลตฟอร์มที่ให้มา แต่จะอนุญาตให้อุปกรณ์ความปลอดภัยเพื่อจำกัดความเสียหายจากสถานการณ์ที่ไม่คาดคิด Modern C จะหลีกเลี่ยงอุปกรณ์ความปลอดภัยที่ไม่มีประสิทธิภาพ 100% ในการควบคุมทุกสิ่ง


3
@ DavidThornley: บางทีตัวอย่างของฉันอาจบอบบางเกินไป ถ้าintเป็น 32 บิตแล้วจะได้รับการเลื่อนตำแหน่งให้ลงนามx intตัดสินจากเหตุผลที่ผู้เขียนของมาตรฐานที่คาดหวังว่าการใช้งานที่ไม่แปลกจะถือว่าการลงนามและประเภทที่ไม่ได้ลงชื่อในแฟชั่นเทียบเท่านอกเฉพาะบางกรณี แต่ GCC บางครั้ง "การเพิ่มประสิทธิภาพ" ในรูปแบบที่แตกถ้าuint16_tโดยuint16_tคูณผลตอบแทนถัวเฉลี่ยผลเกิน INT_MAX แม้ว่าผลลัพธ์จะถูกใช้เป็นค่าที่ไม่ได้ลงชื่อ
supercat

4
ตัวอย่างที่ดี นี่คือเหตุผลหนึ่งว่าทำไมเราควร (ใน GCC หรือเสียงดังกราว) -Wconversionรวบรวม
Davislor

2
@Davislor: อ่าฉันเพิ่งสังเกตุว่า godbolt กลับลำดับของคอมไพเลอร์ในรายการดังนั้นการเลือก gcc รุ่นสุดท้ายในรายการให้ผลล่าสุดมากกว่าเร็วที่สุด ฉันไม่คิดว่าคำเตือนมีประโยชน์อย่างยิ่งเนื่องจากมีแนวโน้มที่จะตั้งค่าสถานะสถานการณ์จำนวนมากเช่นreturn x+1;ที่ไม่ควรเป็นปัญหาและการส่งผลให้ uint32_t จะยับยั้งข้อความโดยไม่แก้ไขปัญหา
supercat

2
@supercat การกำจัดการทดสอบนั้นไม่มีจุดหมายหากจำเป็นต้องใช้คอมไพเลอร์เพื่อให้การทดสอบกลับมาอยู่ในสถานที่ที่แตกต่างกัน
user253751

3
@immibis: คำสั่ง "ที่ตรวจสอบแล้ว" อาจอนุญาตให้คอมไพเลอร์แทนที่การทดสอบจำนวนมากหรือการตรวจสอบที่จะดำเนินการหลายครั้งภายในลูปด้วยการทดสอบเดี่ยวซึ่งอาจถูกยกขึ้นนอกลูป นั่นดีกว่าการกำหนดให้โปรแกรมเมอร์เพิ่มการตรวจสอบที่ไม่ต้องการในรหัสเครื่องสำหรับโปรแกรมเพื่อให้ตรงตามข้อกำหนดเพื่อจุดประสงค์ในการตรวจสอบว่าคอมไพเลอร์ไม่ได้ "ตรวจสอบการเพิ่มประสิทธิภาพ" ที่จำเป็นเพื่อให้ตรงตามข้อกำหนด
supercat

7

ความถูกต้องมีหลายชั้นในภาษา เพื่อเพิ่มความเป็นนามธรรม:

  • โปรแกรมไม่กี่ข้อผิดพลาด (เฉพาะที่สามารถพิสูจน์ความถูกต้อง) คนอื่น ๆ กล่าวถึงแล้วว่าการควบคุมข้อผิดพลาดนั้นเป็นประเด็นด้านความปลอดภัยที่เป็นรูปธรรมที่สุด ภาษาที่ทำงานในเครื่องเสมือนเช่น Java และ. net มักจะปลอดภัยกว่าในแง่นี้: ข้อผิดพลาดของโปรแกรมจะถูกดักจับและจัดการตามวิธีที่กำหนด 1
  • ในระดับต่อไปข้อผิดพลาดที่ตรวจพบในเวลารวบรวมแทนที่จะเป็นเวลาทำงานทำให้ภาษาปลอดภัยยิ่งขึ้น โปรแกรมที่ถูกต้องทางวากยสัมพันธ์ควรมีความหมายถูกต้องมากที่สุด แน่นอนว่าคอมไพเลอร์ไม่สามารถรู้ภาพรวมได้ดังนั้นสิ่งนี้จึงเกี่ยวข้องกับระดับรายละเอียด ประเภทข้อมูลที่แข็งแกร่งและชัดเจนเป็นหนึ่งในด้านความปลอดภัยในระดับนี้ อาจกล่าวได้ว่าภาษาควรทำให้เกิดข้อผิดพลาดบางประเภทได้ยาก(ข้อผิดพลาดประเภทการเข้าถึงนอกขอบเขตตัวแปรที่ไม่กำหนดค่าเริ่มต้น ฯลฯ ) ข้อมูลชนิดรันไทม์เช่นอาร์เรย์ที่มีข้อมูลความยาวหลีกเลี่ยงข้อผิดพลาด ฉันตั้งโปรแกรม Ada 83 ในวิทยาลัยและพบว่าโดยทั่วไปแล้วโปรแกรม Ada ที่รวบรวมอาจมีลำดับความผิดพลาดน้อยกว่าโปรแกรม C ที่เกี่ยวข้อง เพียงแค่ใช้ความสามารถของ Ada ในการกำหนดประเภทจำนวนเต็มซึ่งไม่สามารถกำหนดได้โดยไม่ต้องมีการแปลงอย่างชัดเจน: ยานอวกาศทั้งหมดขัดข้องเพราะเท้าและเมตรสับสนซึ่งหนึ่งสามารถหลีกเลี่ยงกับ Ada ได้เล็กน้อย

  • ในระดับต่อไปภาษาควรจัดให้มีวิธีการหลีกเลี่ยงรหัสสำเร็จรูป หากคุณต้องเขียนคอนเทนเนอร์ของคุณเองหรือเรียงลำดับของพวกเขาหรือเรียงต่อกันของพวกเขาหรือถ้าคุณต้องเขียนของคุณเองstring::trim()คุณจะทำผิดพลาด เนื่องจากระดับนามธรรมเพิ่มขึ้นเกณฑ์นี้เกี่ยวข้องกับภาษาที่เหมาะสมเช่นเดียวกับห้องสมุดมาตรฐานของภาษา

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

  • ภาษาควรให้ความหมายสำหรับการทำให้เป็นโมดูลและการทำงานร่วมกัน ประเภทที่แข็งแกร่งและซับซ้อนที่ผู้ใช้กำหนดเองจากด้านบนช่วยสร้าง API ที่แสดงออก

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


1แต่เนื่องจากโดยปกติแล้วความถูกต้องของเครื่องเสมือนไม่สามารถพิสูจน์ได้ว่าภาษาดังกล่าวอาจค่อนข้างขัดแย้งไม่เหมาะสำหรับข้อกำหนดด้านความปลอดภัยที่เข้มงวดมาก


1
+1 สำหรับเลเยอร์ที่ชัดเจนโดยอธิบายเลเยอร์ คำถามสำหรับคุณยานอวกาศทั้งลำเกิดข้อผิดพลาดเพราะเท้าและเมตรสับสนซึ่งอาจจะหลีกเลี่ยงไม่ได้กับ Ada คุณกำลังพูดถึงMars Probe Lost เนื่องจากข้อผิดพลาดทางคณิตศาสตร์อย่างง่ายหรือไม่? คุณรู้ภาษาที่ใช้สำหรับยานอวกาศหรือไม่
scaaahu

2
@scaaahu ใช่ฉันคิดว่าฉันพูดถึงเรื่องนั้น ไม่ฉันไม่รู้จักภาษา ที่จริงแล้วการอ่านรายงานดูเหมือนว่าข้อมูลที่ส่งโดยโพรบได้รับการประมวลผลโดยซอฟต์แวร์บนโลกที่สร้างไฟล์ข้อมูลซึ่งถูกใช้เพื่อกำหนดระดับแรงขับ การพิมพ์ภาษาแบบง่ายไม่สามารถใช้ได้ในสถานการณ์นี้ แต่พวกเขามีปัญหาหลายอย่างเกี่ยวกับซอฟต์แวร์ภาคพื้นดินและรูปแบบไฟล์ข้อมูลซึ่งทำให้เกิดความสับสนในการตรวจสอบปัญหาก่อน ดังนั้นเรื่องราวจึงไม่ได้เป็นข้อโต้แย้งโดยตรงสำหรับการพิมพ์ที่แข็งแกร่ง แต่ก็ยังเป็นเรื่องที่ควรระวัง
Peter - Reinstate Monica

1

โปรดอย่าพูดว่า PL ทุกคนมีคำสั่งที่ไม่ปลอดภัย เราสามารถใช้เซ็ตย่อยที่ปลอดภัยได้เสมอ

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


ความปลอดภัยมีหลายมิติและเป็นส่วนตัว

บางภาษามีการทำงานจำนวนมากที่ "ไม่ปลอดภัย" อื่น ๆ มีการดำเนินการดังกล่าวน้อยลง ในบางภาษาวิธีการเริ่มต้นในการทำบางสิ่งนั้นไม่ปลอดภัยโดยเนื้อแท้ วิธีอื่นที่เป็นค่าเริ่มต้นนั้นปลอดภัย ในบางภาษามีชุดย่อย "ไม่ปลอดภัย" ที่ชัดเจน ในภาษาอื่น ๆ ไม่มีชุดย่อยดังกล่าวเลย

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

และในบางภาษาความหมายที่แตกต่างกันทั้งหมดของ "ความปลอดภัย" ถือว่าเป็นส่วนย่อยของความปลอดภัยประเภท (เช่น Rust และ Pony บรรลุความปลอดภัยด้ายผ่านคุณสมบัติของระบบประเภท)


-1

คำตอบนี้กว้างขึ้นอีกเล็กน้อย คำว่าปลอดภัยและความปลอดภัยในช่วงไม่กี่สิบปีที่ผ่านมาได้ถูกทำลายโดยบางส่วนที่มุ่งเน้นทางการเมืองของสังคมที่พูดภาษาอังกฤษเช่นการใช้งานทั่วไปของพวกเขาเกือบจะไม่มีคำนิยาม อย่างไรก็ตามสำหรับวิชาทางเทคนิคฉันยังคงกลับไปเพื่อกำหนด "ความปลอดภัย" และ "ปลอดภัย" เป็น: อุปกรณ์ที่ป้องกันการใช้งานโดยไม่ตั้งใจหรือสิ่งที่ทำให้การใช้งานโดยไม่ตั้งใจทำได้ยากขึ้นและสถานะของการอยู่ภายใต้การคุ้มครองของอุปกรณ์ดังกล่าว .
ดังนั้นภาษาที่ปลอดภัยจึงมีอุปกรณ์ที่จะ จำกัด คลาสของข้อบกพร่องบางประเภท แน่นอนว่าข้อ จำกัด นั้นมาพร้อมกับความไม่สะดวกหรือในบางกรณีและนั่นก็ไม่ได้หมายความว่าภาษาที่ "ไม่ปลอดภัย" จะส่งผลให้เกิดข้อบกพร่อง เช่นฉันไม่มีจุกความปลอดภัยในส้อมของฉันและมีการจัดการมานานหลายทศวรรษโดยไม่มีความพยายามมากเพื่อหลีกเลี่ยงการแทงตาขณะกิน แน่นอนว่ามีความพยายามน้อยกว่าการใช้จุกไม้ก๊อก ดังนั้นความปลอดภัยจึงมาพร้อมกับราคาที่ต้องพิจารณา (cork fork เป็นการอ้างอิงถึงตัวละครของ Steve Martin)

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