.NET Out Of Memory Exception - Đã sử dụng 1,3 GB nhưng đã cài đặt 16 GB


91

Tôi nhận được ngoại lệ Hết bộ nhớ trong ứng dụng c # của mình khi mức sử dụng bộ nhớ cho ứng dụng vượt quá khoảng 1,3 GB.

Tôi đã gặp vấn đề này tương tự trên máy 32 bit với bộ nhớ 3gb và điều đó có ý nghĩa hồi đó, nhưng bây giờ tôi đã nâng cấp phần cứng lên máy 64 bit với bộ nhớ 16GB với bo mạch chủ cao cấp và RAM nhưng hết bộ nhớ. ngoại lệ vẫn xảy ra sau 1,3GB!

Tôi biết rằng không có đối tượng nào trên 2GB và dù sao thì 1,3 cũng ít hơn 2GB, vì vậy giới hạn MS 2GB được tích hợp sẵn trên một đối tượng không có khả năng là vấn đề ...

Có vẻ như có một cửa sổ kill-switch nào đó khi một ứng dụng đạt đến ngưỡng sử dụng bộ nhớ nhất định ... Sau đó, có lẽ nên có một cách để cấu hình điều này trong sổ đăng ký?

Chúng tôi rất trân trọng bất kỳ sự giúp đỡ nào!


9
Hệ điều hành của bạn có phải là 64bit không?
fge

9
Ngay cả khi hệ điều hành của bạn là 64bit, đảm bảo quá trình của bạn cũng là 64bit (hoặc AnyCPU)
Knowleech

Câu trả lời:


90

Không có sự khác biệt nào cho đến khi bạn biên dịch sang cùng một kiến ​​trúc đích. Tôi cho rằng bạn đang biên dịch cho 32kiến trúc bit trong cả hai trường hợp.

Nó đáng nói rằng OutOfMemoryExceptioncũng có thể được tăng lên nếu bạn nhận được 2GBbộ nhớ được phân bổ bởi một bộ sưu tập duy nhất trong CLR (nói List<T>) trên cả kiến trúc 3264 bit.

Để có thể hưởng lợi từ độ tốt của bộ nhớ trên 64kiến trúc bit, bạn phải biên dịch64 kiến trúc bit nhắm mục tiêu mã của mình . Sau đó, một cách tự nhiên, tệp nhị phân của bạn sẽ chỉ chạy trên 64bit, nhưng sẽ được hưởng lợi từ khả năng có thêm dung lượng trống trong RAM.


8
Còn về AnyCPU?
dtb

1
Có, AnyCPU cũng là một tùy chọn, nơi bạn có tùy chọn cho mã phụ thuộc vào kiến ​​trúc JIT. Nhưng việc nhắm mục tiêu các kiến ​​trúc cụ thể vẫn có thể có lợi, trong trường hợp bạn có (giả sử) tài nguyên không được quản lý. Tôi không biết kiến ​​trúc của OP là gì.
Tigran

4
Tôi biết điều đó :) - Cảm ơn Tigran, tôi đã xây dựng lại giải pháp trong x64 và ngoại lệ đã biến mất.
Paceman

63

Như đã đề cập, biên dịch ứng dụng trong x64 cung cấp cho bạn nhiều bộ nhớ khả dụng hơn.

Nhưng trong trường hợp người ta phải xây dựng một ứng dụng trong x86, có một cách để tăng giới hạn bộ nhớ từ 1,2GB lên 4GB (đây là giới hạn thực tế cho các quy trình 32 bit):

Trong thư mục VC / bin của thư mục cài đặt Visual Studio, phải có một editbin.exetệp. Vì vậy, trong cài đặt mặc định của tôi, tôi thấy nó dưới

C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\editbin.exe

Để làm cho chương trình hoạt động, có thể trước tiên bạn phải thực thi vcvars32.battrong cùng một thư mục. Sau đó a

editbin /LARGEADDRESSAWARE <your compiled exe file>

là đủ để cho phép chương trình của bạn sử dụng RAM 4GB. <your compiled exe file>là exe, được VS tạo ra trong khi biên dịch dự án của bạn.

Nếu bạn muốn tự động hóa hành vi này mỗi khi bạn biên dịch dự án của mình, hãy sử dụng sự kiện Post-Build sau cho dự án đã thực thi:

if exist "$(DevEnvDir)..\tools\vsvars32.bat" (
   call "$(DevEnvDir)..\tools\vsvars32.bat"
   editbin /largeaddressaware "$(TargetPath)"
)

Sidenote: Điều tương tự có thể được thực hiện với việc devenv.execho phép Visual Studio cũng sử dụng RAM 4GB thay vì 1.2GB (nhưng trước tiên hãy sao lưu bản cũ devenv.exe).


Cảm ơn rất nhiều. Điều này làm việc cho tôi. Nhưng chúng tôi có bất kỳ vấn đề nào được xác định sau khi tăng giới hạn bộ nhớ lên 4GB.
Maverick

28

Điều đáng nói là mặc định cho bộ biên dịch 'Bất kỳ CPU nào' hiện sẽ chọn hộp kiểm 'Ưu tiên 32bit'. Được đặt thành AnyCPU, trên hệ điều hành 64bit với 16 GB RAM vẫn có thể gặp ngoại lệ hết bộ nhớ ở mức 2gb nếu điều này được chọn.

Prefer32BitCheckBox


2
Điều này hoàn toàn được giải quyết ra của tôi về vấn đề bộ nhớ và lưu chúng tôi một tấn của sự thất vọng
RSSM

2

Có vẻ như bạn có kiến ​​trúc 64 bit, tốt - nhưng phiên bản 32 bit của thời gian chạy .NET và / hoặc phiên bản 32 bit của Windows.

Và như vậy, không gian địa chỉ có sẵn cho quy trình của bạn vẫn như cũ, nó không thay đổi so với thiết lập trước đó của bạn.

Nâng cấp lên cả HĐH 64bit và phiên bản .NET 64bit;)


1

Ứng dụng của bạn đang chạy dưới dạng quy trình 64 hay 32bit? Bạn có thể kiểm tra điều này trong trình quản lý tác vụ.

Có thể là, nó đang chạy ở định dạng 32bit, mặc dù toàn bộ hệ thống đang chạy trên 64bit.

Nếu 32bit, thư viện của bên thứ ba có thể gây ra điều này. Nhưng trước tiên hãy đảm bảo rằng ứng dụng của bạn đang biên dịch cho "Mọi CPU", như đã nêu trong phần nhận xét.


0

Nếu bạn có Windows 32 bit, phương pháp này không hoạt động nếu không làm theo các cài đặt.

  1. Chạy dấu nhắc cmd.exe (quan trọng: Chạy với tư cách quản trị viên)
  2. gõ bcdedit.exe và chạy
  3. Nhìn vào các thông số "tăng người dùng" và không có thì hãy viết câu lệnh sau
  4. bcdedit / set boostuserva 3072
  5. và một lần nữa bước 2 và kiểm tra các thông số

Chúng tôi đã thêm cài đặt này và khối này đã bắt đầu.

if exist "$(DevEnvDir)..\tools\vsvars32.bat" (
   call "$(DevEnvDir)..\tools\vsvars32.bat"
   editbin /largeaddressaware "$(TargetPath)"
)

Thông tin thêm - lệnh increaseuserva: https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/bcdedit--set

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.