ประโยชน์ด้านความปลอดภัยของระบบประเภทใด


47

ในJavaScript: ส่วนที่ดีโดย Douglas Crockford เขากล่าวถึงในบทที่สืบทอดของเขา

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

ก่อนอื่นเลยความปลอดภัยคืออะไร? การป้องกันข้อมูลเสียหายหรือแฮกเกอร์หรือระบบทำงานผิดปกติ ฯลฯ ?

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


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

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

4
@BenjaminGruenbaum สิ่งที่อธิบายของคุณมีอยู่แล้วในภาษาเช่น OCaml แบบคงที่ มันเรียกว่าการพิมพ์แบบโครงสร้างจริง ๆ แล้วค่อนข้างเก่าการพิมพ์เล็กน้อยนั้นใหม่กว่า
jozefg

2
@BenjaminGruenbaum: ... อะไรนะ! เห็นได้ชัดว่ามันไม่สามารถอธิบายได้ในภาษาที่พิมพ์แบบคงที่หรือมิฉะนั้นการเขียนคอมไพเลอร์สำหรับภาษาเหล่านั้นจะเป็นไปไม่ได้
BlueRaja - Danny Pflughoeft

6
@BenjaminGruenbaum: ความคิดเห็นของคุณมีค่าและกระดาษนั้นน่าสนใจ แต่ก็ไม่ได้อ้างสิทธิ์ของคุณว่า "มันมักจะไม่สามารถอธิบายได้ในภาษาแบบคงที่เช่น Java เช่นกัน" เพราะมันแสดงให้เห็นว่ามันเป็น decidable ใน C # และเปิดคำถาม ไม่ว่าจะเป็น undecidable ใน Java (และต่อไป IME เมื่อคอมไพเลอร์สำหรับภาษาที่พิมพ์แบบสแตติกไม่สามารถตัดสินใจได้ว่ามีบางสิ่งที่พิมพ์ได้ดีมันจะปฏิเสธมัน (หรือล้มเหลวในการคอมไพล์) ดังนั้นความไม่แน่นอนคือความรำคาญมากกว่าช่องโหว่ในประเภท ความปลอดภัย)
ruakh

คำตอบ:


82

ระบบพิมพ์ป้องกันข้อผิดพลาด

ระบบประเภทกำจัดโปรแกรมที่ผิดกฎหมาย พิจารณารหัสไพ ธ อนต่อไปนี้

 a = 'foo'
 b = True
 c = a / b

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

ในทำนองเดียวกันระบบประเภทที่ดีกว่าจะออกกฎข้อผิดพลาดเพิ่มเติม ถ้าเรากระโดดขึ้นไปสู่ระบบขั้นสูงแบบพิเศษเราสามารถพูดสิ่งนี้:

 Definition divide x (y : {x : integer | x /= 0}) = x / y

ขณะนี้ระบบพิมพ์รับประกันว่าไม่มีข้อผิดพลาดหารด้วย 0

ข้อผิดพลาดประเภทใด

นี่คือรายการสั้น ๆ ของข้อผิดพลาดที่ระบบพิมพ์สามารถป้องกันได้

  1. ข้อผิดพลาดนอกช่วง
  2. การฉีด SQL
  3. ข้อสรุปทั่วไปเกี่ยวกับความปลอดภัย 2 ประการ (การตรวจสอบเรื่องมลทินคืออะไรในPerl )
  4. ข้อผิดพลาดนอกลำดับ (การลืมเรียก init)
  5. การบังคับให้ใช้ชุดย่อยของค่า (ตัวอย่างเช่นจำนวนเต็มมากกว่า 0 เท่านั้น)
  6. ลูกแมวชั่วร้าย (ใช่มันเป็นเรื่องตลก)
  7. ข้อผิดพลาดการสูญเสียความแม่นยำ
  8. ข้อผิดพลาดของซอฟต์แวร์ transactional memory (STM) (ต้องมีความบริสุทธิ์ซึ่งต้องใช้ชนิดด้วย)
  9. generalizing 8 ควบคุมผลข้างเคียง
  10. ค่าคงที่ของโครงสร้างข้อมูล (ต้นไม้ไบนารีมีความสมดุลหรือไม่)
  11. ลืมข้อยกเว้นหรือโยนผิด

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

กรณีศึกษา: แคลคูลัสแลมบ์ดาที่พิมพ์

Alright ให้ตรวจสอบที่ง่ายที่สุดของระบบการพิมพ์ทั้งหมดเพียงแค่พิมพ์แลมบ์ดาแคลคูลัส

โดยทั่วไปมีสองประเภทคือ

Type = Unit | Type -> Type

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

ลองคิดดูสิเราสามารถใช้ระบบพิมพ์เพื่อรับประกันว่าโปรแกรมของเราจะไม่วนซ้ำตลอดไปใช่ไหม?

ทางอ้อมเป็นแบบไดนามิก

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

ดังนั้นประเภทไดนามิกไม่ได้ออกกฎบางโปรแกรม แต่จะกำหนดเส้นทางโปรแกรมที่ผิดรูปแบบไปสู่การกระทำที่กำหนดไว้อย่างดีเช่นการโยนข้อยกเว้น

TLDR

ดังนั้นความยาวและความสั้นของมันก็คือระบบประเภทนั้นจะออกกฎบางโปรแกรม หลายโปรแกรมแตกในทางใดทางหนึ่งด้วยระบบประเภทเราหลีกเลี่ยงโปรแกรมที่เสียหายเหล่านี้


25
+1 สำหรับการคอมไพล์เทียบเท่ากับการเขียนการทดสอบจำนวนมาก
Dan Neely

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

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

5
@DonalFellows ฟังก์ชัน Ackermann ไม่ใช่การเรียกซ้ำแบบดั้งเดิมแม้ว่าจะเป็นฟังก์ชันที่คำนวณได้ทั้งหมด
Taymon

4
@sacundim แน่นอนภาษาเช่น agda อนุญาตให้มีการตรวจสอบจำนวนรวมที่เป็นทางเลือกและในบางกรณีที่คุณต้องการเรียกซ้ำโดยพลการคุณสามารถถามเป็นอย่างดีนั่นเป็นระบบที่ลื่นไหล
jozefg

17

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

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


15

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

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

if (someRareCondition)
     a = 1
else
     a = {1, 2, 3}

// 10 lines below
k = a.length

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


5
และตัวเชื่อมฉลาดใน IDE เช่น WebStorm JavaScript สามารถพูดว่า "เป็นไปได้ที่ไม่ได้กำหนดการอ้างอิงถึง a.length สำหรับหมายเลข a" สิ่งนี้ไม่ได้ให้กับเราโดยมีระบบประเภทที่ชัดเจน
Benjamin Gruenbaum

4
1. ไม่คงเส้นคงวาอย่างรุนแรง 2. @BenjaminGruenbaum ใช่ แต่นี่ทำโดยการไล่กราฟของการมอบหมายในพื้นหลังคิดว่ามันเหมือนล่ามขนาดเล็กที่พยายามคิดว่าสิ่งที่กำลังจะเกิดขึ้น ยิ่งยากกว่าตอนที่ประเภทมอบให้คุณฟรี
jozefg

6
@BenjaminGruenbaum: อย่าสับสนโดยปริยาย / ชัดเจนกับ strong / อ่อนแอ ยกตัวอย่างเช่น Haskell มีระบบที่แข็งแกร่งอย่างไม่น่าเชื่อที่ทำให้ภาษาอื่น ๆ ส่วนใหญ่น่าอับอาย แต่เนื่องจากการตัดสินใจออกแบบภาษาทำให้บางอย่างนั้นยังมีความสามารถในการอนุมานประเภทสากลเกือบทั้งหมดทำให้มันเป็นภาษาที่พิมพ์โดยนัยอย่างยิ่ง (ที่คุณควรใช้เพราะคนประเภทด้อยสามารถอนุมานได้จากสิ่งที่คุณเขียนไม่ใช่สิ่งที่คุณหมายถึง!)
Phoshi

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

1
@BenjaminGruenbaum: อ้ายุติธรรมพอ ถึงกระนั้นก็ตามก็ยังมีบางกรณีที่ไม่มีตัววิเคราะห์ JS แบบคงที่ที่สามารถทำการพิมพ์ประเภทเดียวกันกับภาษาที่พิมพ์ได้อย่างรุนแรงซึ่งจะให้การแก้นั้นในกรณีทั่วไปต้องแก้ปัญหาการหยุดชะงัก Haskell ต้องทำการตัดสินใจในการออกแบบเพียงเล็กน้อยเพื่อให้ได้การอนุมานชนิดใกล้ 100% และ C # / Scala ไม่สามารถสรุปได้ทุกอย่าง แน่นอนในกรณีเหล่านั้นมันไม่สำคัญเพราะคุณสามารถระบุประเภทได้อย่างชัดเจน - ใน Javascript หมายความว่าแม้แต่ตัววิเคราะห์แบบสแตติกที่ดีที่สุดก็ไม่สามารถตรวจสอบรหัสของคุณได้อีกต่อไป
Phoshi

5

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

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

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

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


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

@MattFenwick สิ่งที่คุณรู้สึกว่าเป็นประโยชน์หลักของการพิมพ์แบบไดนามิก?
GlenPeterson

ระบบพิมพ์แบบสแตติกทั่วไปปฏิเสธโปรแกรมที่พิมพ์ได้ดีจำนวนมากโดยการออกแบบ ( ทางเลือก ) (BTW คำวิจารณ์ของฉันถูกกำกับเฉพาะในย่อหน้าที่ 3 และ 4)

4

บทนำ

ความปลอดภัยของประเภทสามารถทำได้ด้วยภาษาแบบคงที่ (รวบรวม, การตรวจสอบประเภทคงที่) และ / หรือรันไทม์ (การประเมินการตรวจสอบประเภทแบบไดนามิก) ภาษา ตามที่วิกิพีเดียอธิบายว่า'... ระบบพิมพ์ที่แข็งแกร่งเป็นระบบที่ไม่มีข้อผิดพลาดประเภทรันไทม์ที่ไม่ถูกตรวจสอบ (ed Luca Cardelli) ในการเขียนอื่น ๆ การไม่มีข้อผิดพลาดรันไทม์ที่ไม่ได้ตรวจสอบเรียกว่าความปลอดภัยหรือความปลอดภัยของประเภท ... '

ความปลอดภัย - การตรวจสอบประเภทคงที่

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

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

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

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

ความปลอดภัย - การตรวจสอบประเภทรันไทม์

ตัวอย่างเช่น Erlang เป็นภาษาที่ประกาศชนิดที่ตรวจสอบประเภทแบบไดนามิกที่ทำงานบนเครื่องเสมือน รหัส Erlang สามารถรวบรวมไบต์ อาจเป็นภาษาที่มีความสำคัญต่อภารกิจที่สำคัญที่สุดและมีรายงานว่า Erlang มีความน่าเชื่อถือของเก้า 9 (99.9999999% หรือไม่เกิน 31.5 msecs ต่อปี)

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


2
ฉันคัดค้าน "พิมพ์อย่างยิ่ง" คุณหมายถึงพิมพ์แบบคงที่ ประเภทที่
แข็งแกร่ง

@ jozefg จุดที่ดี ฉันจะแก้ไขโพสต์
AsymLabs

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

3
@jozefg: ฉันมักจะคิดว่าพิมพ์อย่างยิ่งหมายความว่าแต่ละค่ามีประเภทคงที่ (เช่นจำนวนเต็ม, สตริง, ฯลฯ ) ในขณะที่พิมพ์อย่างอ่อนหมายความว่าค่าที่สามารถถูก coerced กับค่าประเภทอื่นถ้ามันสะดวกที่จะทำ ดังนั้น. เช่นใน Python (พิมพ์อย่างมาก) 1 + "1"ให้ส่งข้อยกเว้นในขณะที่ PHP (พิมพ์อย่างอ่อน) 1 + "1"สร้าง2(สตริง"1"จะถูกแปลงเป็นจำนวนเต็มโดยอัตโนมัติ1)
Giorgio

1
@Giorgio พร้อมคำจำกัดความเช่น Java ไม่ได้พิมพ์อย่างมาก แต่ในหลายกรณีมันก็อ้างว่าเป็น ไม่มีความหมายต่อคำเหล่านี้ พิมพ์แบบ Strong / Weak มีคำจำกัดความที่แม่นยำมากขึ้นเช่น "ฉันชอบ / ไม่ใช้ภาษานี้" เช่น jozefg พูดว่า
Esailija

1

ประโยชน์ด้านความปลอดภัยของระบบประเภทจะหายไป

ก่อนอื่นเลยความปลอดภัยคืออะไร? การป้องกันข้อมูลเสียหายหรือแฮกเกอร์หรือระบบทำงานผิดปกติ ฯลฯ ?

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

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

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

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

f : (Int,Int) -> String

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

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

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

พิจารณา

Foo x = new Foo(3,4,5,6);
f((Int)x,(Int)x);

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

สิ่งหนึ่งที่สามารถสร้างระบบที่แตกต่างและดีกว่าคือการแยกการปลดเปลื้อง (A) x โดยที่ x ก่อนหน้าเคสเป็นประเภท B ยกเว้นว่า B เป็น subtype (หรือ subobject) ของ A แนวคิดของทฤษฎี subtyping ถูกนำมาใช้ในการรักษาความปลอดภัย เพื่อลบความเป็นไปได้ของการโจมตีแบบเต็มล้น / อันเดอร์โฟลว์

สรุป

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


1

ข้อได้เปรียบอย่างหนึ่งที่ยังไม่ได้กล่าวถึงสำหรับระบบศูนย์พิมพ์ที่มีความจริงที่ว่าหลายโปรแกรมอ่านมากกว่าที่เขียนไว้และในหลาย ๆ กรณีระบบประเภทอาจอนุญาตให้ข้อมูลจำนวนมากถูกระบุในลักษณะที่กระชับและง่าย ย่อยโดยใครบางคนกำลังอ่านรหัส ในขณะที่ประเภทพารามิเตอร์ไม่ได้ใช้แทนความคิดเห็นเชิงพรรณนาคนส่วนใหญ่จะพบว่าอ่านได้เร็วกว่า: "ระยะทาง int" หรือDistance As Int32กว่าจะอ่าน "ระยะทางจะต้องเป็นจำนวนเต็ม +/- 2147483647"; การผ่านเศษส่วนอาจให้ผลลัพธ์ที่ไม่สอดคล้องกัน "นอกจากนี้ประเภทพารามิเตอร์สามารถช่วยลดช่องว่างระหว่างสิ่งที่การใช้งานเฉพาะของ API เกิดขึ้นเมื่อเทียบกับผู้โทรที่มีสิทธิ์พึ่งพาตัวอย่างเช่นหากการใช้ Javascript ของ API ใช้ พารามิเตอร์ในทางที่จะบีบบังคับสตริงใด ๆ กับรูปแบบตัวเลขก็อาจจะยังไม่ชัดเจนว่าสายที่ได้รับอนุญาตให้ขึ้นอยู่กับพฤติกรรมดังกล่าวหรือถ้าการใช้งานอื่น ๆ ของความผิดปกติ API อาจถ้าได้รับสาย. มีวิธีการที่มีพารามิเตอร์ที่มีการระบุเป็นDoubleหากว่า ทำให้ชัดเจนว่าค่าสตริงใด ๆ จะต้องถูกบังคับโดยผู้เรียกก่อนที่จะถูกส่งมีวิธีการที่มีการโอเวอร์โหลดที่ยอมรับDoubleและอื่น ๆ ที่ยอมรับString จะทำให้ค่อนข้างชัดเจนว่าผู้โทรที่ถือสายจะได้รับอนุญาตให้ส่งพวกเขาเช่นนี้


0

ก่อนอื่นเลยความปลอดภัยคืออะไร? ป้องกันข้อมูลเสียหายหรือแฮกเกอร์หรือระบบทำงานผิดปกติ ฯลฯ ?

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

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

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

ระบบประเภทที่พึ่งพานั้นเป็นระบบที่ใช้กันทั่วไปมากที่สุดซึ่งคุณสามารถบังคับใช้คุณสมบัติใดก็ได้ที่คุณต้องการ มันไม่จำเป็นต้องเป็นเรื่องง่ายที่จะทำเช่นนั้น แต่เป็นคุณสมบัติที่มีความซับซ้อนอาจมีการขาดมารยาทของGödel

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