เป็นไปได้หรือไม่ที่จะประเมินความปลอดภัยของโปรแกรมสำหรับรหัสที่กำหนดเอง?


10

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

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

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

คำเตือน :

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

2
รหัสโดยพลการ? ไม่ฉันคิดว่าคุณไม่สามารถพิสูจน์ความปลอดภัยของรหัสที่มีประโยชน์มากที่สุดได้เนื่องจาก I / O และข้อยกเว้นฮาร์ดแวร์
Telastyn

7
ทำไมคุณไม่สนใจปัญหาการหยุดชะงัก ทุกตัวอย่างเดียวที่คุณพูดถึงและอื่น ๆ อีกมากมายได้รับการพิสูจน์แล้วว่าเทียบเท่ากับการแก้ปัญหาการหยุดชะงัก, ปัญหาฟังก์ชั่น, ทฤษฎีของข้าวหรือทฤษฎีอื่น ๆ อีกมากมายของ Undecidability: ความปลอดภัยของตัวชี้, หน่วยความจำ - ความปลอดภัย -safety ข้อยกเว้นความปลอดภัย, ความบริสุทธิ์, I / O ความปลอดภัยล็อคความปลอดภัยรับประกันความคืบหน้า ฯลฯ ลังเลปัญหาเป็นหนึ่งในที่ง่ายคุณสมบัติคงเป็นไปได้ว่าคุณอาจจะต้องการที่จะรู้ว่าทุกสิ่งทุกอย่างที่คุณรายการคือยากมาก .
Jörg W Mittag

3
หากคุณเพียงแค่ใส่ใจในแง่บวกที่ผิดพลาดและยินดีที่จะยอมรับข้อผิดพลาดที่ผิดพลาดฉันมีอัลกอริทึมที่จำแนกทุกอย่าง: "ปลอดภัยหรือไม่ไม่"
Caleth

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

คำตอบ:


8

ในที่สุดสิ่งที่เรากำลังพูดถึงที่นี่คือรวบรวมเวลาและรันไทม์

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

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

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

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

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

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

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

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


3

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

แต่ระบบประเภทค่อนข้าง จำกัด :

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

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

เนื่องจากข้อ จำกัด เหล่านี้ระบบพิมพ์มักจะตรวจสอบคุณสมบัติที่ค่อนข้างอ่อนแอซึ่งง่ายต่อการพิสูจน์เช่นว่าฟังก์ชันถูกเรียกใช้ด้วยค่าประเภทที่ถูกต้อง แต่ถึงกระนั้นก็ตามนั่นก็มีข้อ จำกัด อย่างมากในเรื่องของการแสดงออกดังนั้นจึงเป็นเรื่องปกติที่จะมีวิธีแก้ปัญหา (เช่นinterface{}ใน Go, dynamicC #, ObjectJava, void*C) หรือแม้แต่การใช้ภาษาที่หลีกเลี่ยงการพิมพ์แบบคงที่

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

ภาษาได้รับการออกแบบพร้อมกับระบบชนิดของพวกเขา เป็นเรื่องยากที่ระบบชนิดใหม่จะถูกกำหนดในภาษาที่มีอยู่ (แต่ดูเช่น MyPy, Flow หรือ TypeScript) ภาษาจะพยายามทำให้ง่ายต่อการเขียนรหัสที่สอดคล้องกับระบบประเภทเช่นโดยเสนอคำอธิบายประกอบประเภทหรือโดยการแนะนำง่ายต่อการพิสูจน์โครงสร้างการไหลของการควบคุม ภาษาที่แตกต่างกันอาจจบลงด้วยการแก้ปัญหาที่แตกต่างกัน เช่น Java มีแนวคิดของfinalตัวแปรที่ได้รับมอบหมายเพียงครั้งเดียวคล้ายกับmutตัวแปรที่ไม่ใช่ของ Rust :

final int x;
if (...) { ... }
else     { ... }
doSomethingWith(x);

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

let x = if ... { ... } else { ... };
do_something_with(x)

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

ถ้าเราจะใช้ระบบการพิมพ์สนิมสไตล์ Java เราจะมีปัญหาใหญ่กว่าที่: วัตถุ Java ไม่ได้มีคำอธิบายประกอบกับอายุการใช้งานดังนั้นเราจะต้องรักษาพวกเขาเป็นหรือ&'static SomeClass Arc<dyn SomeClass>นั่นจะทำให้ข้อพิสูจน์ที่อ่อนแอลง Java ยังไม่มีแนวคิดระดับประเภทของการเปลี่ยนไม่ได้ดังนั้นเราจึงไม่สามารถแยกความแตกต่างระหว่าง&และ&mutประเภท เราจะต้องปฏิบัติต่อวัตถุใด ๆ ในฐานะที่เป็น Cell หรือ Mutex แม้ว่าสิ่งนี้อาจถือว่าการค้ำประกันที่แข็งแกร่งกว่า Java ที่นำเสนอจริง ในที่สุด Rust ไม่มีแนวคิดเกี่ยวกับการสืบทอดการใช้งานสไตล์ Java

TL; DR:ระบบชนิดเป็นตัวพิสูจน์ทฤษฎีบท แต่จะถูก จำกัด ด้วยปัญหาความสามารถในการตัดสินใจและความกังวลด้านประสิทธิภาพ คุณไม่สามารถใช้ระบบประเภทเดียวและนำไปใช้กับภาษาอื่นได้เนื่องจากไวยากรณ์ภาษาของเป้าหมายอาจไม่ให้ข้อมูลที่จำเป็นและเนื่องจากความหมายอาจเข้ากันไม่ได้


3

ปลอดภัยแค่ไหน?

ใช่มันเกือบจะเป็นไปได้ที่จะเขียนตัวตรวจสอบ: โปรแกรมของคุณเพียงแค่ส่งคืนค่าคงที่ UNSAFE คุณจะถูก 99% ของเวลา

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

และแม้ว่าเซิร์ฟเวอร์ของคุณกำลังทำงานอยู่ในกรงฟาราเดย์ในบังเกอร์กระบวนการเพื่อนบ้านอาจดำเนินการเอาเปรียบ rowhammer และทำการพลิกในโปรแกรม Rust ที่ปลอดภัยของคุณ

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

ตลกกันการตรวจสอบอัตโนมัติ

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

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

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


1

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

อย่างไรก็ตามผลลัพธ์ของทัวริงไม่ได้จำกัดความเป็นไปได้ของโปรแกรมที่สามารถ 100% ของเวลาทั้ง (1) ตรวจสอบรหัสอย่างปลอดภัย (2) ตรวจสอบว่ารหัสไม่ปลอดภัยหรือ (3) anthropomorphically ยกมือขึ้นแล้วพูดว่า "เฮ็คฉันไม่รู้" คอมไพเลอร์ของ Rust พูดโดยทั่วไปอยู่ในหมวดหมู่นี้


ดังนั้นตราบใดที่คุณมีตัวเลือก“ ไม่แน่ใจ” ใช่ไหม
อนุรักษ์สิ่งแวดล้อม

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

1

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

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

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

ดังนั้นการวิจัยส่วนใหญ่จึงเน้นไปที่การพิสูจน์ การติดต่อกับ Curry – Howard ระบุว่าการพิสูจน์ความถูกต้องและระบบการพิมพ์เป็นสิ่งหนึ่งและสิ่งเดียวกันดังนั้นการวิจัยเชิงปฏิบัติส่วนใหญ่จึงอยู่ภายใต้ชื่อระบบการพิมพ์ โดยเฉพาะที่เกี่ยวข้องกับการสนทนานี้คือCoqและIdrissนอกเหนือจากสนิมซึ่งคุณได้กล่าวไปแล้ว Coq เข้าใกล้ปัญหาพื้นฐานทางวิศวกรรมจากอีกทางหนึ่ง การพิสูจน์ความถูกต้องของรหัสโดยพลการในภาษา Coq ก็สามารถสร้างรหัสที่รันโปรแกรมพิสูจน์ ในขณะเดียวกัน Idriss ใช้ระบบประเภทที่พึ่งพาเพื่อพิสูจน์รหัสโดยพลการใน Haskell ล้วนๆเหมือนภาษา สิ่งที่ทั้งสองภาษาทำคือผลักปัญหาหนักของการสร้างข้อพิสูจน์ที่สามารถทำงานได้ไปยังผู้เขียนช่วยให้ตัวตรวจสอบชนิดเพื่อมุ่งเน้นไปที่การตรวจสอบหลักฐาน การตรวจสอบหลักฐานเป็นปัญหาที่ง่ายกว่ามาก แต่สิ่งนี้ทำให้ภาษาทำงานได้ยากขึ้นมาก

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

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