ที่อยู่หน่วยความจำบนฮีปถูกนำมาใช้ซ้ำหรือไม่

คำอธิบายเพิ่มเติมของคำถามชื่อเรื่องคือตามลำดับ ให้ฉันอธิบายสถานการณ์ของฉัน

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

วัตถุจำนวนมากในรายการมีตัวชี้ไปยังวัตถุอื่นๆ ในรายการเดียวกัน

ก่อนที่ฉันจะยกเลิกการอ้างอิงตัวชี้ใดๆ เหล่านั้น ฉันต้องการใช้ฟังก์ชัน CheckAgainstList(ptr*) เพื่อให้แน่ใจว่าวัตถุหนึ่งชี้ไปยังวัตถุอื่นในรายการเดียวกัน ดังนั้นจึงไม่ได้ชี้ไปยังวัตถุที่ถูกลบไปแล้ว

สวมหมวกเหล็กวิลาดตอนนี้ เป็นไปได้ไหม?

  1. วัตถุ A มีตัวชี้ไปยังวัตถุ B โดยมีที่อยู่หน่วยความจำ 0x00988e50
  2. วัตถุ B ถูกลบ
  3. วัตถุ C ถูกสร้างขึ้นและวางลงในพื้นที่หน่วยความจำที่เพิ่งว่าง 0x00988e50
  4. CheckAgainstList(ptr*) คืนค่าเป็นจริงเมื่อเราตรวจสอบตัวชี้เนื่องจากวัตถุ C อยู่ในรายการและอยู่ในที่อยู่หน่วยความจำเดียวกันกับ B ที่เคยครอบครอง

ตอนนี้เรามีจุดบกพร่องเพราะ A คิดว่ามันมีตัวชี้ไปที่ B แต่ B หายไปแล้ว และ C ก็เข้ามาแทนที่

ข้อผิดพลาดที่อาจเกิดขึ้นนี้เป็นไปได้หรือไม่?


person user1438585    schedule 22.06.2012    source แหล่งที่มา
comment
ไม่ใช่แค่เป็นไปได้ - เป็นไปได้ด้วย หากคุณปล่อยให้ B ว่างและจัดสรร C ทันทีหลังจากนั้น มีแนวโน้มว่าจะมีการใช้งานฮีปจำนวนมากที่คุณจะได้รับบัฟเฟอร์เดิมคืนมา   -  person Rafael Baptista    schedule 22.06.2012
comment
มาที่นี่เพื่อดูว่าเหตุการณ์นี้เกิดขึ้นบ่อยเพียงใดหลังจากเห็นว่ามีการใช้ซ้ำอย่างชัดเจน (สำหรับข้อมูลประเภทเดียวกัน) ใช่ :)   -  person mlvljr    schedule 27.01.2016


คำตอบ (5)


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

ปัญหาที่คุณพยายามแก้ไขอาจแก้ไขได้ด้วย weak_ptr ซึ่งสามารถตรวจสอบความถูกต้องได้ก่อน มันถูกใช้

person Mark Ransom    schedule 22.06.2012

ใช่แล้ว จุดบกพร่องนั้นเป็นไปได้ทั้งหมด

โดยพื้นฐานแล้วสิ่งที่คุณทำอยู่นั้นค่อนข้างอันตรายและจะทำให้เกิดข้อบกพร่องได้อย่างรวดเร็ว คุณอาจจะดีที่สุดโดยใช้การอ้างอิงที่นับ ptr อัจฉริยะบางประเภท C ++ 11 รวม std::shared_ptr ซึ่งหมายความว่าคุณสามารถใช้แทนตัวชี้ปกติได้ วิธีนี้จะไม่ทำให้หน่วยความจำว่างจนกว่าทุกอย่างจะเสร็จสิ้น และจะบรรเทาปัญหาดังที่คุณอธิบาย

ตัวเลือกอื่นของคุณคือการสแกนวัตถุอื่น ๆ ทั้งหมดเพื่อดูว่าพวกเขาอ้างอิงถึง 'B' ที่ถูกลบหรือไม่และทำบางอย่างเช่น "null" ออกจากพอยน์เตอร์ไปยังพอยน์เตอร์ที่ถูกลบไปแล้ว

person Goz    schedule 22.06.2012

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

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

person zxcdw    schedule 22.06.2012

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

person Jerome    schedule 22.06.2012

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

person Daniel    schedule 22.06.2012