มันจะเป็นอย่างไร หน่วยความจำของตัวแปรโลคัลไม่สามารถเข้าถึงได้นอกฟังก์ชั่นหรือไม่
คุณเช่าห้องพักที่โรงแรม คุณวางหนังสือไว้ในลิ้นชักบนสุดของโต๊ะข้างเตียงแล้วเข้านอน คุณเช็คเอาต์เช้าวันรุ่งขึ้น แต่ "ลืม" เพื่อมอบกุญแจ คุณขโมยกุญแจ!
หนึ่งสัปดาห์ต่อมาคุณกลับไปที่โรงแรมอย่าเช็คอินแอบเข้าไปในห้องเก่าของคุณด้วยกุญแจที่ถูกขโมยและมองเข้าไปในลิ้นชัก หนังสือของคุณยังอยู่ที่นั่น น่าอัศจรรย์!
นั่นเป็นอย่างไร เนื้อหาของลิ้นชักห้องพักของโรงแรมไม่สามารถเข้าถึงได้หากคุณยังไม่ได้เช่าห้อง
เห็นได้ชัดว่าสถานการณ์สามารถเกิดขึ้นได้ในโลกจริง ไม่มีแรงลึกลับที่ทำให้หนังสือของคุณหายไปเมื่อคุณไม่ได้รับอนุญาตให้อยู่ในห้องอีกต่อไป หรือมีพลังลึกลับที่ป้องกันไม่ให้คุณเข้าไปในห้องด้วยกุญแจที่ถูกขโมย
การจัดการโรงแรมไม่จำเป็นต้องลบหนังสือของคุณ คุณไม่ได้ทำสัญญากับพวกเขาที่กล่าวว่าหากคุณทิ้งของไว้พวกเขาจะทำลายมันให้คุณ หากคุณลักลอบเข้าห้องของคุณด้วยกุญแจที่ถูกขโมยเพื่อนำมันกลับมาพนักงานรักษาความปลอดภัยของโรงแรมไม่จำเป็นต้องจับคุณเข้ามาคุณไม่ได้ทำสัญญากับพวกเขาที่กล่าวว่า "ถ้าฉันพยายามแอบเข้าไปในห้อง ห้องต่อมาคุณจะต้องหยุดฉัน " แต่คุณได้เซ็นสัญญากับพวกเขาที่กล่าวว่า "ฉันสัญญาว่าจะไม่แอบเข้าไปในห้องของฉันในภายหลัง" ซึ่งเป็นสัญญาที่คุณทำผิด
ในสถานการณ์เช่นนี้อะไรจะเกิดขึ้น หนังสือเล่มนี้สามารถอยู่ที่นั่น - คุณโชคดี สามารถมีหนังสือของคนอื่นและคุณอาจอยู่ในเตาหลอมของโรงแรม บางคนอาจมีสิทธิ์เมื่อคุณเข้ามาฉีกหนังสือเป็นชิ้น ๆ โรงแรมอาจลบตารางและจองทั้งหมดและแทนที่ด้วยตู้เสื้อผ้า ทั้งโรงแรมอาจจะถูกฉีกและแทนที่ด้วยสนามฟุตบอลและคุณจะต้องตายด้วยการระเบิดในขณะที่คุณแอบไปรอบ ๆ
คุณไม่รู้ว่าจะเกิดอะไรขึ้น เมื่อคุณเช็คเอาต์จากโรงแรมและขโมยกุญแจเพื่อใช้งานอย่างผิดกฎหมายในภายหลังคุณละทิ้งสิทธิ์ที่จะอยู่ในโลกที่คาดการณ์ได้และปลอดภัยเพราะคุณเลือกที่จะทำผิดกฎของระบบ
c ++ ไม่ใช่ภาษาที่ปลอดภัย มันจะช่วยให้คุณมีความสุขที่จะทำลายกฎของระบบ หากคุณพยายามทำสิ่งผิดกฎหมายและโง่เขลาเหมือนกลับไปที่ห้องที่คุณไม่ได้รับอนุญาตให้เข้าไปในและค้นหาผ่านโต๊ะที่อาจไม่ได้อยู่ที่นั่นอีกต่อไป C ++ จะไม่หยุดคุณ ภาษาที่ปลอดภัยกว่า C ++ แก้ปัญหานี้ด้วยการ จำกัด พลังงานของคุณ - โดยการควบคุมปุ่มอย่างเข้มงวดตัวอย่างเช่น
UPDATE
ความดีของพระเจ้าคำตอบนี้ได้รับความสนใจอย่างมาก (ฉันไม่แน่ใจว่าทำไม - ฉันคิดว่ามันเป็นเพียงการเปรียบเทียบ "สนุก" เล็กน้อย แต่อะไรก็ตาม)
ฉันคิดว่ามันน่าจะอัปเดตเล็กน้อยด้วยความคิดด้านเทคนิคเพิ่มเติม
คอมไพเลอร์อยู่ในธุรกิจของการสร้างรหัสที่จัดการการจัดเก็บข้อมูลที่จัดการโดยโปรแกรมนั้น มีหลายวิธีในการสร้างรหัสเพื่อจัดการหน่วยความจำ แต่เมื่อเวลาผ่านไปสองเทคนิคพื้นฐานได้กลายเป็นที่ยึดที่มั่น
ประการแรกคือการมีพื้นที่เก็บข้อมูล "อายุยืน" บางส่วนที่ "อายุการใช้งาน" ของแต่ละไบต์ในการจัดเก็บ - นั่นคือช่วงเวลาที่เกี่ยวข้องกับตัวแปรโปรแกรมบางอย่าง - ไม่สามารถทำนายล่วงหน้าได้อย่างง่ายดาย ของเวลา คอมไพเลอร์สร้างการเรียกเป็น "ตัวจัดการฮีป" ที่รู้วิธีจัดสรรพื้นที่เก็บข้อมูลแบบไดนามิกเมื่อมีความจำเป็นและเรียกคืนเมื่อไม่ต้องการใช้อีกต่อไป
วิธีที่สองคือการมีพื้นที่เก็บข้อมูล "อายุสั้น" ที่รู้จักกันดีของอายุการใช้งานของแต่ละไบต์ ที่นี่อายุการใช้งานเป็นไปตามรูปแบบ "การทำรัง" ตัวแปรที่มีอายุการใช้งานยาวนานที่สุดของตัวแปรเหล่านี้จะถูกจัดสรรก่อนตัวแปรที่มีอายุสั้นอื่น ๆ และจะถูกปล่อยให้เป็นอิสระล่าสุด ตัวแปรที่มีอายุสั้นกว่าจะได้รับการจัดสรรหลังจากตัวแปรที่มีอายุการใช้งานยาวนานที่สุดและจะถูกปล่อยให้เป็นอิสระก่อนตัวแปรเหล่านั้น อายุการใช้งานของตัวแปรที่มีอายุสั้นกว่านี้คือ“ ซ้อนกัน” ภายในอายุการใช้งานของตัวแปรที่มีอายุการใช้งานยาวนานกว่า
ตัวแปรโลคัลตามรูปแบบหลัง เมื่อมีการป้อนเมธอดตัวแปรโลคัลของมันจะยังมีชีวิตอยู่ เมื่อวิธีนั้นเรียกใช้วิธีอื่นตัวแปรท้องถิ่นของวิธีการใหม่จะมีชีวิต พวกเขาจะตายก่อนที่ตัวแปรโลคอลของวิธีแรกจะตาย ลำดับสัมพัทธ์ของจุดเริ่มต้นและจุดสิ้นสุดของอายุการเก็บรักษาที่เกี่ยวข้องกับตัวแปรท้องถิ่นสามารถดำเนินการได้ล่วงหน้า
ด้วยเหตุนี้ตัวแปรในท้องถิ่นจึงถูกสร้างขึ้นเป็นหน่วยเก็บข้อมูลในโครงสร้างข้อมูล "สแต็ก" เนื่องจากสแต็กมีคุณสมบัติที่สิ่งแรกที่ผลักดันให้มันเป็นสิ่งสุดท้ายที่โผล่ออกมา
มันเหมือนโรงแรมตัดสินใจที่จะให้เช่าห้องตามลำดับเท่านั้นและคุณไม่สามารถเช็คเอาท์ได้จนกว่าทุกคนที่มีหมายเลขห้องพักสูงกว่าที่คุณเช็คเอาท์
งั้นลองคิดสแต็คกันดู ในระบบปฏิบัติการหลายระบบคุณจะได้รับหนึ่งสแต็คต่อเธรดและสแต็กถูกจัดสรรให้มีขนาดคงที่แน่นอน เมื่อคุณเรียกเมธอดสิ่งต่างๆจะถูกพุชลงในสแต็ก หากคุณส่งตัวชี้ไปที่สแต็กกลับออกมาจากวิธีการของคุณเช่นเดียวกับโปสเตอร์ดั้งเดิมที่นี่นั่นเป็นเพียงตัวชี้ไปที่ตรงกลางของบล็อกหน่วยความจำล้านไบต์ที่ถูกต้องทั้งหมด ในการเปรียบเทียบของเราคุณเช็คเอาท์จากโรงแรม เมื่อคุณทำคุณเพิ่งเช็คเอาต์จากห้องที่มีผู้ครอบครองมากที่สุด หากไม่มีใครเช็คอินหลังจากคุณและคุณกลับไปที่ห้องของคุณอย่างผิดกฎหมายสิ่งของทุกอย่างของคุณรับประกันว่าจะยังคงอยู่ที่โรงแรมนี้
เราใช้สแต็คสำหรับร้านค้าชั่วคราวเพราะราคาถูกและง่ายมาก การนำ C ++ มาใช้ไม่จำเป็นต้องใช้สแต็กสำหรับการจัดเก็บในท้องถิ่น มันสามารถใช้กอง ไม่ได้เพราะจะทำให้โปรแกรมช้าลง
ไม่จำเป็นต้องใช้ C ++ เพื่อทิ้งขยะที่คุณทิ้งไว้ในกองซ้อนที่ไม่ได้แตะต้องเพื่อให้คุณสามารถกลับมาใช้ใหม่ได้ในภายหลังโดยผิดกฎหมาย มันถูกกฎหมายอย่างสมบูรณ์สำหรับคอมไพเลอร์ในการสร้างรหัสที่เปลี่ยนกลับเป็นศูนย์ทุกอย่างใน "ห้อง" ที่คุณเพิ่งว่าง ไม่ได้เพราะอีกครั้งนั่นจะมีราคาแพง
การใช้งาน C ++ นั้นไม่จำเป็นเพื่อให้แน่ใจว่าเมื่อสแต็กลดขนาดลงอย่างมีเหตุผลที่อยู่ที่เคยใช้งานได้จะถูกแมปไปยังหน่วยความจำ การใช้งานได้รับอนุญาตให้บอกระบบปฏิบัติการ "เราเสร็จแล้วโดยใช้หน้าของสแต็กตอนนี้จนกว่าฉันจะพูดเป็นอย่างอื่นออกข้อยกเว้นที่ทำลายกระบวนการถ้าใครสัมผัสหน้าสแต็คที่ถูกต้องก่อนหน้านี้" อีกครั้งการใช้งานไม่ได้ทำเพราะมันช้าและไม่จำเป็น
แต่การใช้งานจะช่วยให้คุณทำผิดพลาดและหนีไปได้ เวลาส่วนใหญ่. จนกระทั่งวันหนึ่งมีอะไรบางอย่างที่น่ากลัวเกิดผิดพลาดและกระบวนการระเบิด
นี่เป็นปัญหา มีกฎมากมายและง่ายต่อการทำลายโดยไม่ตั้งใจ ฉันมีหลายครั้งอย่างแน่นอน และที่แย่กว่านั้นปัญหามักเกิดขึ้นเมื่อหน่วยความจำถูกตรวจพบว่ามีความเสียหายหลายพันล้านนาโนวินาทีหลังจากความเสียหายเกิดขึ้นเมื่อมันยากมากที่จะคิดออกว่าใครทำให้มันยุ่งเหยิง
ภาษาที่ปลอดภัยสำหรับหน่วยความจำเพิ่มเติมแก้ปัญหานี้ได้โดย จำกัด การใช้พลังงานของคุณ ใน "ปกติ" C # จะไม่มีวิธีรับที่อยู่ของท้องถิ่นและส่งคืนหรือเก็บไว้ใช้ในภายหลัง คุณสามารถระบุที่อยู่ของท้องถิ่นได้ แต่ภาษานั้นได้รับการออกแบบมาอย่างชาญฉลาดเพื่อที่จะไม่สามารถใช้งานได้หลังจากสิ้นสุดอายุการใช้งานในท้องถิ่น ในการรับที่อยู่ของท้องถิ่นและส่งกลับมาคุณต้องใส่คอมไพเลอร์ในโหมดพิเศษ "ไม่ปลอดภัย" และใส่คำว่า "ไม่ปลอดภัย" ในโปรแกรมของคุณเพื่อเรียกความสนใจจากข้อเท็จจริงที่ว่าคุณอาจทำ สิ่งที่อันตรายที่อาจทำลายกฎ
สำหรับการอ่านเพิ่มเติม:
address of local variable ‘a’ returned
; การแสดง valgrindInvalid write of size 4 [...] Address 0xbefd7114 is just below the stack ptr