Wyjątek dotyczący braku pamięci .NET - używane 1,3 GB, ale zainstalowano 16 GB

91

Otrzymuję wyjątek braku pamięci w mojej aplikacji C #, gdy użycie pamięci dla aplikacji przekracza około 1,3 GB.

Miałem ten sam problem na 32-bitowej maszynie z 3 GB pamięci i wtedy miało to sens, ale teraz zaktualizowałem sprzęt do maszyny 64-bitowej z pamięcią 16 GB z wysokiej klasy płytą główną i pamięcią RAM, ale brakiem pamięci wyjątek nadal występuje po 1.3 GB!

Wiem, że nie ma pojedynczych obiektów powyżej 2 GB, a 1,3 to i tak mniej niż 2 GB, więc wbudowany limit MS 2 GB na pojedynczy obiekt raczej nie będzie problemem ...

Wygląda na to, że istnieje jakiś wyłącznik awaryjny systemu Windows, gdy aplikacja osiąga określony próg użycia pamięci ... Czy powinien być sposób skonfigurowania tego, być może w rejestrze?

Każda pomoc będzie mile widziana!

Paceman
źródło
9
Czy Twój system operacyjny jest również 64-bitowy?
fge
9
Nawet jeśli Twój system operacyjny jest 64-bitowy, upewnij się, że Twój proces jest również 64-bitowy (lub AnyCPU)
Knowleech

Odpowiedzi:

90

Nie ma różnicy, dopóki nie skompilujesz do tej samej architektury docelowej. I załóżmy kompilujesz dla 32bitowej architektury w obu przypadkach.

Warto wspomnieć, że OutOfMemoryExceptionmożna to również podnieść, jeśli otrzymasz 2GBpamięć przydzieloną przez jedną kolekcję w CLR (powiedzmy List<T>) zarówno na architekturach, jak 32i na 64bitach.

Aby móc korzystać z dobroci pamięci w 64architekturze bitowej, należy skompilować kod ukierunkowany na 64architekturę bitową. Po tym, oczywiście, twój plik binarny będzie działał tylko na 64bitach, ale skorzysta z możliwości posiadania większej ilości miejsca w pamięci RAM.

Tigran
źródło
8
A co z AnyCPU?
dtb,
1
Tak, AnyCPU jest również opcją, w której masz opcję kodu zależnego od architektury JIT. Jednak ukierunkowanie na określoną architekturę nadal może przynieść korzyści w przypadkach, gdy masz niezarządzane (powiedzmy) zasoby. Nie mam pojęcia, o co chodzi w architekturze OP.
Tigran,
4
Wiedziałem o tym :) - Dzięki Tigran, przebudowałem rozwiązanie w x64 i wyjątek zniknął.
Paceman,
63

Jak już wspomniano, kompilacja aplikacji w x64 zapewnia znacznie więcej dostępnej pamięci.

Ale w przypadku, gdy trzeba zbudować aplikację w x86, istnieje sposób na zwiększenie limitu pamięci z 1,2 GB do 4 GB (co jest faktycznym limitem dla procesów 32-bitowych):

W folderze VC / bin katalogu instalacyjnego programu Visual Studio musi znajdować się editbin.exeplik. Więc w mojej domyślnej instalacji znajduję to pod

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

Aby program działał, być może musisz najpierw wykonać go vcvars32.batw tym samym katalogu. Następnie

editbin /LARGEADDRESSAWARE <your compiled exe file>

wystarczy, aby Twój program używał 4 GB pamięci RAM. <your compiled exe file>to plik exe, który VS wygenerował podczas kompilacji projektu.

Jeśli chcesz zautomatyzować to zachowanie za każdym razem, gdy kompilujesz projekt, użyj następującego zdarzenia Post-Build dla wykonywanego projektu:

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

Uwaga: to samo można zrobić z devenv.exeprogramem Visual Studio, aby zamiast 1,2 GB używać 4 GB pamięci RAM (ale najpierw wykonaj kopię zapasową starego devenv.exe).

Desty
źródło
Wielkie dzięki. To działa dla mnie. Ale czy mamy zidentyfikowane problemy po zwiększeniu limitu pamięci do 4 GB?
Maverick
28

Warto wspomnieć, że domyślnie dla kompilacji „Dowolny procesor” zaznacza teraz pole wyboru „Preferuj 32-bitowy”. Ustawiony na AnyCPU w 64-bitowym systemie operacyjnym z 16 GB pamięci RAM może nadal powodować wyjątek braku pamięci przy 2 GB, jeśli jest zaznaczone.

Prefer32BitCheckBox

tonycoupland
źródło
2
To całkowicie rozwiązało moje problemy z
brakiem
2

Wygląda na to, że masz 64-bitowy łuk, dobrze - ale 32-bitową wersję środowiska uruchomieniowego .NET i / lub 32-bitową wersję systemu Windows.

W związku z tym przestrzeń adresowa dostępna dla twojego procesu jest nadal taka sama, nie zmieniła się od poprzedniej konfiguracji.

Uaktualnij do 64-bitowej wersji systemu operacyjnego i 64-bitowej wersji .NET;)

fge
źródło
1

Czy Twoja aplikacja działa jako proces 64- lub 32-bitowy? Możesz to sprawdzić w menedżerze zadań.

Możliwe, że działa jako 32-bitowy, mimo że cały system działa na 64-bitowym.

Jeśli jest to wersja 32-bitowa, przyczyną może być biblioteka innej firmy. Ale najpierw upewnij się, że Twoja aplikacja kompiluje się dla "Dowolnego procesora", jak stwierdzono w komentarzach.

Jacco
źródło
0

Jeśli masz 32-bitowy system Windows, ta metoda nie działa bez następujących ustawień.

  1. Uruchom polecenie cmd.exe (ważne: Uruchom jako administrator)
  2. wpisz bcdedit.exe i uruchom
  3. Spójrz na parametry „Increaseuserva” i nie ma wtedy możliwości napisania następującego stwierdzenia
  4. bcdedit / set Increaseuserva 3072
  5. i ponownie krok 2 i sprawdź params

Dodaliśmy te ustawienia i ten blok się rozpoczął.

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

Więcej informacji - polecenie increaseuserva: https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/bcdedit--set

Mehmet Kurt
źródło