Làm thế nào để .NET framework phân bổ bộ nhớ cho OutOfMemoryException?


144

Trong C ++, thực sự có thể đưa ra một ngoại lệ theo giá trị mà không cần phân bổ bộ nhớ trên một đống, vì vậy tình huống này có ý nghĩa. Nhưng trong .NET framework OutOfMemoryExceptionlà một kiểu tham chiếu, do đó nó được phân bổ trên một đống. Làm thế nào để .NET framework phân bổ bộ nhớ cho OutOfMemoryExceptionkhi không có đủ bộ nhớ để tạo một đối tượng mới?


6
Câu hỏi tuyệt vời. Có lẽ đủ bộ nhớ được dành riêng cho tình huống đó.
GreatAndPowerfulOz

19
Chỉ cần thêm vào các câu trả lời khác đã có ở đây, hãy nhớ rằng OOM có nghĩa là khối bạn yêu cầu không thể được phân bổ. Nếu bạn yêu cầu 100Mb và khối có sẵn lớn nhất mà thời gian chạy có thể tìm thấy chỉ là 99Mb, nó sẽ thất bại. Nhưng một ngoại lệ OOM chỉ cần một vài byte bộ nhớ. Vì vậy, chỉ vì phân bổ của bạn thất bại, điều đó không có nghĩa là không còn bộ nhớ. Nhưng tất nhiên, có khả năng bộ thực thi dự trữ một số bộ nhớ để tự bảo vệ mình trong tình huống này
Jason Williams

4
Nhân tiện, giả định của bạn về C ++ là không chính xác. Tùy thuộc vào trình biên dịch, các ngoại lệ cũng có thể được phân bổ trên heap. Trình biên dịch MS thì không, nhưng trong C ++ ABI chung, các trường hợp ngoại lệ được phân bổ trên heap, ngoại trừ có một bộ đệm khẩn cấp preallocated nhỏ sẽ được sử dụng thay thế nếu không còn chỗ trống trên heap.
Sebastian Redl

Câu trả lời:


163

Nó được preallocated bởi thời gian chạy. Nếu bạn khám phá hàng đống quy trình được quản lý, bạn sẽ tìm thấy một trường hợp ngoại lệ đó.

Dưới đây là các trường hợp ngoại lệ được áp dụng của ứng dụng 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
Nhưng các nhà xây dựng củaOutOfMemoryException được gọi là.
Tim Schmelter

36
Thời gian chạy không phải chơi theo cùng quy tắc với mã của bạn. Một ví dụ khác là nếu bạn ném StackOverflowExceptionbạn có thể bắt được nó, nhưng nếu thời gian chạy ném ngoại lệ đó, bạn không thể bắt được nó (theo mặc định).
Brian Rasmussen

8
Phần lớn các cơ chế cơ bản của CLR thực sự được viết bằng "C" và "C ++". Vì vậy, hoàn toàn có thể đối tượng là "mới có tại chỗ" hoặc bộ nhớ bị thao túng.
GreatAndPowerfulOz

2
@hvd Tác dụng phụ là gì? OOM có cho dấu vết ngăn xếp không? Tôi sẽ có mặc dù phần còn lại của thông tin là khá tĩnh?
James Barrass

7
Điều gì xảy ra nếu hai trường hợp ngoại lệ của những người có cùng loại được yêu cầu vì hai luồng ném chúng cùng một lúc?
Traubenfuchs

42

Khi gặp phải tình trạng hết bộ nhớ trong thời gian chạy, nó sẽ gọi throwOutOfMemory . Điều này gọi Exception :: GetOOMException , cấu trúc đối tượng trên ngăn xếp và sau đó sao chép nó vào một thể hiện toàn cầu được phân bổ tĩnh, sau đó được ném ra.

Đây không phải là ngoại lệ quản lý, tuy nhiên, nó là một ngoại lệ ++ C tuyên bố trong ex.h . Các ngoại lệ C ++ được chuyển đổi thành Ngoại lệ được quản lý trong clrex.cpp , có chứa mã để ném cụ thể OutOfMemoryException được quản lý trước , được phân bổ và xây dựng trong appdomain.cpp .

Lưu ý: Một số tệp nguồn này lớn và có thể treo trình duyệt của bạn trong vài giây trong khi tải phần tô sáng cú pháp.

Các trang web cuộc gọi mà Tim Schmelter liên kết trong một nhận xét về câu trả lời khác không liên quan đến thời gian chạy hết bộ nhớ và không thể xây dựng một đối tượng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.