ทำไมไม่ใช้รหัสปลอดภัยที่ไม่มีการจัดการใน C #


10

มีตัวเลือกใน C # เพื่อเรียกใช้งานโค้ดที่ไม่ได้ตรวจสอบ โดยทั่วไปไม่แนะนำให้ทำเช่นนั้นเนื่องจากรหัสที่ได้รับการจัดการนั้นปลอดภัยกว่าและสามารถเอาชนะปัญหาได้มากมาย

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

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

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

ป.ล. ภูมิหลังของฉัน: ฉันรู้สึกเข้าสู่โลกแห่งการเขียนโปรแกรมและฉันทำงานคนเดียว (ฉันทำมาสองสามปี) และดังนั้นฉันหวังว่าคำถามการออกแบบซอฟต์แวร์นี้จะไม่แปลก ฉันไม่ได้มีคนอื่นที่นั่นเหมือนครูที่จะถามสิ่งนั้น


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

14
ฉันเขียนโค้ดจำนวนมากในช่วงหลายปีที่บางครั้งเกิดข้อผิดพลาดหรือมีการรั่วไหลของหน่วยความจำฉันค่อนข้างแน่ใจว่าไม่มีหน่วยความจำรั่วหรือความเสี่ยงของการล่ม
whatsisname

1
นี่คือตัวอย่างการunsafeใช้งานที่ดี: stackoverflow.com/q/11660127/102937
Robert Harvey

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

1
เพราะแม้ว่าคุณจะแน่ใจว่ารหัสของคุณจะไม่ทำให้เกิดข้อผิดพลาด แต่ก็ยังทำให้เกิดข้อผิดพลาด
user253751

คำตอบ:


27

มันเป็นกรณีของสุภาษิตโบราณที่มีอายุมาก

  • อย่าปรับให้เหมาะสม
  • (สำหรับผู้เชี่ยวชาญเท่านั้น) อย่าเพิ่งเพิ่มประสิทธิภาพ

แต่จริงๆแล้วฉันนึกถึงเหตุผลหลักสามข้อที่ต้องหลีกเลี่ยงรหัสที่ไม่ปลอดภัย

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

  2. ไม่เร็วเท่าที่คุณคิด : อีกประเด็นคือ: ขึ้นอยู่กับปัญหาที่ได้รับอาจไม่ดีขนาดนั้น แม้ว่าตอนนี้ฉันจะไม่พบพวกเขา แต่ฉันจำการศึกษาโดย Google เปรียบเทียบความเร็วของ Java, Scala, Go และ C ++ เมื่อปรับให้เหมาะกับพื้นดินแน่นอนว่า C ++ นั้นเร็วกว่ามาก แต่อัลกอริทึมที่ตั้งโปรแกรมในลักษณะ "สำนวน" ไม่ได้เร็วขนาดนั้นจริงๆ สำนวนในแง่ที่ว่าพวกเขากำลังใช้โครงสร้างมาตรฐานและสำนวน (คอนเทนเนอร์ STL ไม่มีการวนซ้ำที่ไม่ได้ควบคุม ฯลฯ ) Microsoft ทำการทดลองที่คล้ายกันกับ C # และ C ++ Raymond Chen หนึ่งใน Microsoft วิศวกรอันดับต้นต้องเขียนการติดตั้ง std :: string เพื่อเอาชนะ C # (ดู: http://www.codinghorror.com/blog/2005/05/on-managed-code-performance-again.html) สำหรับความพยายามที่น้อยกว่าคุณจะได้ประสิทธิภาพที่ดีพอสมควรในโค้ดที่ได้รับการจัดการดังนั้นจึงมักไม่คุ้มกับปัญหา

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

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

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


4

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

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

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


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


0

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

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


1
ฉันไม่คิดว่ามันเกี่ยวข้องกับความถูกต้องหรือความเรียบง่ายสำหรับเหตุผล ..
จิมมี่ฮอฟฟา

ไม่มีใครพูดถึงการพิสูจน์ความถูกต้องอย่างเป็นทางการ

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

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

1
@fish: ฉันเห็นสิ่งที่คุณพูด มีความสัมพันธ์ระหว่างสิ่งที่ยากที่จะพิสูจน์และบางสิ่งบางอย่างยากที่จะให้เหตุผลเกี่ยวกับ ถ้ามันยากที่จะพิสูจน์ว่าถูกต้องมันก็ยากที่จะแน่ใจว่ามันถูกต้อง
Michael Shaw

0

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

ในทางตรงกันข้าม C # มีข้อดีที่ให้สภาพแวดล้อมการพัฒนาที่ปลอดภัย / มีการจัดการและพิมพ์อย่างรุนแรงเพื่อให้ทำงานอย่างปลอดภัยใน. NET Framework

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

ดังนั้นตัวเลือกในการทำงานกับรหัสที่ไม่ได้รับการจัดการใน. NET Framework เริ่มต้นที่ 4.0 เป็นตัวเลือกสำหรับเคสขนาดเล็กเมื่อคุณแน่ใจว่ามันอาจทำให้คุณได้รับมากกว่าที่ไม่ได้ใช้ ...


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