ตกลงคำตอบบางอย่างเกี่ยวกับ malloc ถูกโพสต์แล้ว
ส่วนที่น่าสนใจคือการทำงานของฟรี (และในทิศทางนี้ malloc ก็สามารถเข้าใจได้ดีขึ้นเช่นกัน)
ในการใช้งาน malloc / ฟรีจำนวนมากโดยปกติแล้วฟรีจะไม่ส่งคืนหน่วยความจำไปยังระบบปฏิบัติการ (หรืออย่างน้อยก็ในกรณีที่หายาก) เหตุผลก็คือคุณจะได้รับช่องว่างในกองของคุณและดังนั้นจึงสามารถเกิดขึ้นได้ว่าคุณเพิ่งเสร็จจาก 2 หรือ 4 GB ของหน่วยความจำเสมือนที่มีช่องว่าง สิ่งนี้ควรหลีกเลี่ยงเนื่องจากเมื่อหน่วยความจำเสมือนเสร็จสิ้นคุณจะมีปัญหาใหญ่มาก อีกเหตุผลคือระบบปฏิบัติการสามารถจัดการหน่วยความจำที่มีขนาดและการจัดตำแหน่งที่เฉพาะเจาะจงเท่านั้น โดยเฉพาะอย่างยิ่ง: โดยปกติระบบปฏิบัติการสามารถจัดการได้เฉพาะบล็อกที่ตัวจัดการหน่วยความจำเสมือนเท่านั้นที่สามารถจัดการได้ (ส่วนใหญ่จะทวีคูณเป็น 512 ไบต์เช่น 4KB)
ดังนั้นการคืน 40 ไบต์ไปยังระบบปฏิบัติการจะไม่ทำงาน ดังนั้นฟรีทำอะไร
ฟรีจะวางบล็อกหน่วยความจำในรายการบล็อกฟรีของตัวเอง โดยปกติจะพยายามรวมบล็อกที่อยู่ติดกันในพื้นที่ที่อยู่ รายการบล็อกฟรีเป็นเพียงรายการวงกลมของหน่วยความจำที่มีข้อมูลการดูแลระบบบางอย่างในการเริ่มต้น นี่คือเหตุผลว่าทำไมการจัดการองค์ประกอบหน่วยความจำขนาดเล็กมากด้วย malloc / free มาตรฐานไม่ได้มีประสิทธิภาพ หน่วยความจำทุกอันต้องการข้อมูลเพิ่มเติมและมีการกระจายตัวของขนาดที่เล็กกว่า
รายการฟรียังเป็นที่แรกที่ malloc ดูเมื่อต้องการหน่วยความจำอันใหม่ มันถูกสแกนก่อนที่จะเรียกใช้หน่วยความจำใหม่จากระบบปฏิบัติการ เมื่อพบก้อนที่ใหญ่กว่าหน่วยความจำที่ต้องการมันจะแบ่งออกเป็นสองส่วน หนึ่งจะถูกส่งกลับไปยังผู้โทรส่วนที่เหลือจะถูกส่งกลับไปยังรายการฟรี
มีการปรับให้เหมาะสมต่าง ๆ มากมายสำหรับพฤติกรรมมาตรฐานนี้ (เช่นสำหรับหน่วยความจำขนาดเล็ก) แต่เนื่องจาก malloc และฟรีต้องเป็นสากลดังนั้นพฤติกรรมมาตรฐานจึงเป็นทางเลือกเสมอเมื่อไม่มีทางเลือกอื่น นอกจากนี้ยังมีการเพิ่มประสิทธิภาพในการจัดการรายการอิสระ - ตัวอย่างเช่นการจัดเก็บชิ้นในรายการที่เรียงตามขนาด แต่การเพิ่มประสิทธิภาพทั้งหมดก็มีข้อ จำกัด เช่นกัน
ทำไมรหัสของคุณถึงพัง:
เหตุผลก็คือโดยการเขียนตัวอักษร 9 ตัว (อย่าลืมไบต์ว่างท้าย) ลงในพื้นที่ที่มีขนาด 4 ตัวอักษรคุณอาจจะเขียนทับข้อมูลการดูแลระบบที่เก็บไว้สำหรับหน่วยความจำอีกอันหนึ่งที่อยู่ด้านหลัง เนื่องจากข้อมูลนี้มักถูกเก็บไว้ที่ "ด้านหน้า" ของหน่วยความจำ) เมื่อว่างแล้วลองใส่ชิ้นของคุณลงในรายการฟรีมันสามารถสัมผัสข้อมูลการดูแลระบบนี้และสะดุดทับตัวชี้ที่เขียนทับ นี่จะทำให้ระบบขัดข้อง
นี่เป็นพฤติกรรมที่ค่อนข้างสง่างาม ฉันเคยเห็นสถานการณ์ที่ตัวชี้ที่หลบหนีอยู่ที่ไหนสักแห่งมีข้อมูลที่เขียนทับในรายการหน่วยความจำฟรีและระบบไม่ได้ผิดพลาดทันที แต่บางรูทีนย่อยในภายหลัง แม้แต่ในระบบที่มีความซับซ้อนปานกลางปัญหาดังกล่าวก็สามารถแก้ไขได้ยากจริงๆ! ในกรณีเดียวที่ฉันเกี่ยวข้องมันใช้เวลาเรา (กลุ่มนักพัฒนาขนาดใหญ่) มาหลายวันเพื่อหาสาเหตุของความผิดพลาด - เนื่องจากอยู่ในตำแหน่งที่แตกต่างไปจากที่ระบุโดยการถ่ายโอนข้อมูลหน่วยความจำ มันเหมือนระเบิดเวลา คุณรู้ไหมว่า "ฟรี" หรือ "malloc" ตัวถัดไปของคุณจะพัง แต่คุณไม่รู้ว่าทำไม!
ปัญหาเหล่านี้เป็นปัญหาของ C / C ++ ที่เลวร้ายที่สุดและสาเหตุหนึ่งที่ทำให้ตัวชี้สามารถเป็นปัญหาได้