เมื่อใดและทำไมพอยน์เตอร์จึงเริ่มมองว่ามีความเสี่ยง


18

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

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

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

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


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

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

4
@DaveInCaz เท่าที่ฉันรู้ว่าการพัฒนาที่เฉพาะเจาะจงคือการประดิษฐ์ของพอยน์เตอร์
หยุดทำร้ายโมนิก้า

5
@nocomprende: สิ่งที่คุณเพิ่งเขียนไม่ได้เป็นข้อเท็จจริงหรือหลักฐานเพียงแค่ความเห็น มีโปรแกรมเมอร์น้อยกว่าในปี 1970 คุณไม่มีหลักฐานใด ๆ ที่บ่งบอกว่าประชากรทุกวันนี้ดีขึ้นหรือแย่ลงที่ "การอ้างอิงทางอ้อม"
whatsisname

3
พอยน์เตอร์ได้รับการพิจารณาว่ามีความเสี่ยงเสมอตั้งแต่วันแรก มันเป็นเพียงการประนีประนอมเพื่อย้ายพวกเขาจากการชุมนุมภาษาระดับสูง
Frank Hileman

คำตอบ:


21

เหตุผลคือการพัฒนาทางเลือกให้กับพอยน์เตอร์

ภายใต้ประทุนตัวชี้ / การอ้างอิง / ฯลฯ ใด ๆ จะถูกนำมาใช้เป็นจำนวนเต็มที่มีที่อยู่หน่วยความจำ (ตัวชี้ aka) เมื่อCออกมาฟังก์ชั่นนี้จะปรากฏเป็นพอยน์เตอร์ นี่หมายความว่าทุกสิ่งที่ฮาร์ดแวร์พื้นฐานสามารถทำได้เพื่อจัดการกับหน่วยความจำสามารถทำได้ด้วยตัวชี้

นี่เป็น "อันตราย" เสมอ แต่อันตรายนั้นสัมพันธ์กัน เมื่อคุณสร้างโปรแกรม 1,000 บรรทัดหรือเมื่อคุณมีกระบวนการคุณภาพซอฟต์แวร์ระดับ IBM แล้วคุณสามารถจัดการกับอันตรายนี้ได้อย่างง่ายดาย อย่างไรก็ตามไม่ใช่ว่าซอฟต์แวร์ทั้งหมดจะได้รับการพัฒนาอย่างนั้น เช่นนี้ความต้องการโครงสร้างที่เรียบง่ายออกมา

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

เมื่อเราย้ายไปที่Javaเราจะย้ายไปสู่ภาษาต่างๆที่ให้การรับรองความปลอดภัย CและC ++ไม่มีให้เลย Java รับประกันว่าจะมีการดำเนินการทางกฎหมายเพียงอย่างเดียวเท่านั้น เมื่อต้องการทำเช่นนี้ java ทำตัวชี้ไปทั้งหมด สิ่งที่พวกเขาพบคือการดำเนินการตัวชี้ / การอ้างอิงส่วนใหญ่ที่ทำในรหัสจริงนั้นเป็นสิ่งที่การอ้างอิงนั้นมีเพียงพอสำหรับ ในบางกรณีเท่านั้น (เช่นการวนซ้ำเร็วผ่านอาร์เรย์) เป็นตัวชี้ที่ต้องการอย่างแท้จริง ในกรณีเหล่านี้จาวาใช้เวลารันไทม์ Hit เพื่อหลีกเลี่ยงการใช้พวกเขา

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

ที่น่าสนใจก็คือภาษาที่ใช้งานได้ซึ่งไม่มีแนวคิดดังกล่าวเลย แต่นั่นเป็นการอภิปรายที่แตกต่างกันมาก


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

6
@JimmyJames จริง สำหรับจุดประสงค์ของคำตอบนี้เส้นแบ่งระหว่างตัวชี้และตัวชี้ไม่ใช่เป็นการสนับสนุนการดำเนินการทางคณิตศาสตร์ของตัวชี้ซึ่งโดยทั่วไปไม่ได้รับการสนับสนุนโดยการอ้างอิง
Cort Ammon - Reinstate Monica

8
@JimmyJames ฉันเห็นด้วยกับการยืนยันของ Cort ว่าตัวชี้เป็นสิ่งที่คุณสามารถทำการดำเนินการทางคณิตศาสตร์ในขณะที่การอ้างอิงไม่ได้ กลไกจริงที่ใช้การอ้างอิงในภาษาเช่น Java เป็นรายละเอียดการใช้งาน
Robert Harvey

3
โดยทั่วไป C และ C ++ ได้ยอมรับการเป็นสมาชิกโดยสมัครใจในสโมสรอันตรายนี้โดยอนุญาตให้มี
rwong

2
โดยวิธีการที่มีอยู่ซีพียูซึ่งความแตกต่างระหว่างตัวชี้และตัวเลข เช่น CISC CPU 48 บิตดั้งเดิมใน IBM AS / 400 ทำเช่นนั้น และในความเป็นจริงมีชั้น abstraction อยู่ภายใต้ระบบปฏิบัติการซึ่งหมายความว่าไม่เพียง แต่ซีพียูแยกแยะความแตกต่างระหว่างตัวเลขและตัวชี้และห้ามคณิตศาสตร์ในตัวชี้ แต่ระบบปฏิบัติการของตัวเองไม่ได้รู้เกี่ยวกับตัวชี้ที่ทุกคนและไม่ทำภาษา . ที่น่าสนใจนี้ทำให้เดิม AS / 400 ระบบใดระบบหนึ่งที่อีกครั้งจากการเขียนโค้ดภาษาสคริปต์ระดับสูงใน C ทำให้คำสั่งของขนาดช้าลง
Jörg W Mittag

10

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

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

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

ถ้าเราดูภาษาการเขียนโปรแกรมที่มาก่อนภาษา C (เช่น Fortran, Algol สำเนียงภาษารวม. Pascal, Cobol, Lisp, …) บางคนสนับสนุนพอยน์เตอร์ C-like โดยเฉพาะอย่างยิ่งแนวคิดตัวชี้โมฆะถูกคิดค้นสำหรับ Algol W ในปี 1965 แต่ไม่มีภาษาใดที่พยายามที่จะเป็นภาษา C-like และมีประสิทธิภาพต่ำ - ภาษาระบบ: Fortran มีความหมายสำหรับการคำนวณทางวิทยาศาสตร์ Algol พัฒนาแนวคิดที่ค่อนข้างทันสมัย มีโครงการวิจัยมากกว่าภาษาระดับอุตสาหกรรมและ Cobol ให้ความสำคัญกับการใช้งานทางธุรกิจ

มีการรวบรวมขยะตั้งแต่ปลายยุค 50 คือก่อนที่ C (ต้นยุค 70) GC ต้องการความปลอดภัยของหน่วยความจำในการทำงานอย่างถูกต้อง ภาษาก่อนและหลัง C ใช้ GC เป็นคุณสมบัติปกติ แน่นอนว่าทำให้ภาษามีความซับซ้อนมากขึ้นและอาจช้าลงซึ่งเห็นได้ชัดโดยเฉพาะในช่วงเวลาของเมนเฟรม ภาษา GC มีแนวโน้มที่จะมุ่งเน้นการวิจัย (เช่น Lisp, Simula, ML) และ / หรือต้องการเวิร์คสเตชั่นที่มีประสิทธิภาพ (เช่น Smalltalk)

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

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

ดังนั้นภาษา "สมัยใหม่" เช่น Java, Ruby, และ C # ไม่ควรตีความว่าเป็นการเอาชนะปัญหาของตัวชี้แบบดิบเช่นใน C แต่ควรถูกมองว่าเป็นภาพวาดจากประเพณีมากมาย - รวมถึง C แต่จากภาษาที่ปลอดภัยกว่าเช่น Smalltalk, Simula หรือเสียงกระเพื่อม


4

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

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

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

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

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

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