.NET Framework จัดสรรหน่วยความจำสำหรับ OutOfMemoryException อย่างไร


144

ใน C ++ เป็นไปได้จริงที่จะโยนข้อยกเว้นตามค่าโดยไม่ต้องจัดสรรหน่วยความจำบนฮีปดังนั้นสถานการณ์นี้จึงสมเหตุสมผล แต่ใน. NET Framework OutOfMemoryExceptionเป็นประเภทอ้างอิงดังนั้นมันจึงถูกจัดสรรบนฮีป . NET Framework จัดสรรหน่วยความจำอย่างไรOutOfMemoryExceptionเมื่อมีหน่วยความจำไม่เพียงพอในการสร้างวัตถุใหม่


6
คำถามที่ยอดเยี่ยม อาจมีการสำรองหน่วยความจำเพียงพอสำหรับสถานการณ์นั้น
GreatAndPowerfulOz

19
เพียงเพิ่มคำตอบอื่น ๆ ที่นี่แล้วโปรดทราบว่า OOM หมายความว่าไม่สามารถจัดสรรบล็อกที่คุณร้องขอได้ หากคุณขอ 100Mb และบล็อกที่ใหญ่ที่สุดที่มีให้รันไทม์สามารถค้นหาได้เพียง 99Mb บล็อกนั้นจะล้มเหลว แต่ข้อยกเว้น OOM ต้องการหน่วยความจำไม่กี่ไบต์เท่านั้น ดังนั้นเนื่องจากการจัดสรรของคุณล้มเหลวนั่นไม่ได้หมายความว่าไม่มีหน่วยความจำเหลืออยู่ แต่แน่นอนว่ามีความเป็นไปได้สูงที่รันไทม์จะสำรองหน่วยความจำบางส่วนเพื่อให้ครอบคลุมในสถานการณ์นี้
Jason Williams

4
สมมติฐานของคุณเกี่ยวกับ C ++ นั้นไม่ถูกต้อง ขึ้นอยู่กับคอมไพเลอร์อาจมีการยกเว้นข้อยกเว้นในฮีป คอมไพเลอร์ MS ไม่ แต่ใน Common C ++ ABI ข้อยกเว้นจะถูกจัดสรรในฮีปยกเว้นว่ามีบัฟเฟอร์ฉุกเฉินขนาดเล็กที่จัดสรรล่วงหน้าที่จะใช้แทนหากไม่มีพื้นที่เหลือบนฮีป
เซบาสเตียนเรดล

คำตอบ:


163

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

นี่คือข้อยกเว้นที่จัดสรรล่วงหน้าของแอป Hello World:

0:003> !dumpheap -stat -type Exception
Statistics:
      MT    Count    TotalSize Class Name
735f2920        1           84 System.ExecutionEngineException
735f28dc        1           84 System.StackOverflowException
735f2898        1           84 System.OutOfMemoryException
735f2744        1           84 System.Exception
735f2964        2          168 System.Threading.ThreadAbortException

4
แต่ตัวสร้างของOutOfMemoryExceptionเรียกว่า
Tim Schmelter

36
รันไทม์ไม่จำเป็นต้องเล่นตามกฎเดียวกับรหัสของคุณ อีกตัวอย่างคือถ้าคุณโยนStackOverflowExceptionคุณสามารถจับได้ แต่ถ้ารันไทม์ส่งข้อยกเว้นนั้นคุณจะไม่สามารถจับได้ (โดยค่าเริ่มต้น)
Brian Rasmussen

8
กลไกพื้นฐานของ CLR ส่วนใหญ่เขียนด้วย "C" และ "C ++" ดังนั้นจึงเป็นไปได้อย่างสิ้นเชิงว่าวัตถุนั้น "เข้าแทนที่" หรือมีการจัดการหน่วยความจำ
GreatAndPowerfulOz

2
@hvd ผลข้างเคียงคืออะไร? OOM ให้การติดตามสแต็กหรือไม่ ฉันจะทราบได้อย่างไรว่าข้อมูลส่วนที่เหลือค่อนข้างคงที่ใช่หรือไม่
James Barrass

7
จะเกิดอะไรขึ้นถ้าจำเป็นต้องมีข้อยกเว้นสองข้อที่มีชนิดเดียวกันเนื่องจากมีสองเธรดพร้อมกัน
Traubenfuchs

42

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

นี้ไม่ได้เป็นข้อยกเว้นการจัดการ แต่ก็ยกเว้น c ++ ประกาศในex.h c ++ ข้อยกเว้นจะถูกแปลงเป็นข้อยกเว้นการจัดการในclrex.cppซึ่งมีรหัสเฉพาะโยน preallocated การจัดการ OutOfMemoryException ซึ่งได้รับการจัดสรรเดิมและสร้างขึ้นในappdomain.cpp

หมายเหตุ: ไฟล์ต้นฉบับเหล่านี้บางไฟล์มีขนาดใหญ่และอาจวางเบราว์เซอร์ของคุณเป็นเวลาหลายวินาทีในขณะที่โหลดการเน้นไวยากรณ์

ไซต์การโทรที่ Tim Schmelter เชื่อมโยงกับความคิดเห็นในคำตอบอื่น ๆ นั้นไม่เกี่ยวข้องกับการรันไทม์ของหน่วยความจำไม่เพียงพอและไม่สามารถสร้างวัตถุได้

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