Excepción de memoria insuficiente de .NET: se usó 1.3GB pero tiene 16GB instalados

91

Recibo una excepción de memoria insuficiente en mi aplicación c # cuando el uso de memoria de la aplicación supera los 1,3 GB.

Tuve el mismo problema en una máquina de 32 bits con 3 GB de memoria y tenía sentido en ese entonces, pero ahora actualicé el hardware a una máquina de 64 bits con 16 GB de memoria con la placa base de gama alta y RAM pero sin memoria. ¡la excepción todavía ocurre después de 1.3GB!

Sé que no hay objetos individuales de más de 2GB y 1.3 es menos de 2GB de todos modos, por lo que es probable que el límite de 2GB incorporado de MS en un solo objeto no sea el problema ...

Parece que hay un interruptor de apagado de Windows de algún tipo cuando una aplicación alcanza un cierto umbral de uso de memoria ... Entonces, ¿debería haber una forma de configurar esto, tal vez en el registro?

¡Cualquier ayuda será apreciada!

Paceman
fuente
9
¿Su sistema operativo también es de 64 bits?
fge
9
Incluso si su sistema operativo es de 64 bits, asegúrese de que su proceso también sea de 64 bits (o AnyCPU)
Knowleech

Respuestas:

90

No hay diferencia hasta que compile en la misma arquitectura de destino. Yo supongo que está compilando para la 32arquitectura de bits en ambos casos.

Vale la pena mencionar que OutOfMemoryExceptiontambién se puede generar si obtiene 2GBmemoria asignada por una sola colección en CLR (digamos List<T>) en ambas arquitecturas 32y 64bit.

Para poder beneficiarse de la bondad de la memoria en la 64arquitectura de bits, debe compilar su código dirigido a la 64arquitectura de bits. Después de eso, naturalmente, su binario se ejecutará solo en 64bit, pero se beneficiará de la posibilidad de tener más espacio disponible en RAM.

Tigran
fuente
8
¿Qué pasa con AnyCPU?
dtb
1
Sí, AnyCPU también es una opción, donde tiene una opción para el código dependiente de la arquitectura JIT. Pero la orientación de la arquitectura específica aún puede beneficiarse, en los casos en que tiene recursos no administrados (por ejemplo). No tengo idea de qué se trata la arquitectura de OP.
Tigran
4
Lo sabía :) - Gracias Tigran, reconstruí la solución en x64 y la excepción desapareció.
Paceman
63

Como ya se mencionó, compilar la aplicación en x64 le brinda mucha más memoria disponible.

Pero en el caso de que uno deba crear una aplicación en x86, hay una manera de aumentar el límite de memoria de 1,2 GB a 4 GB (que es el límite real para procesos de 32 bits):

En la carpeta VC / bin del directorio de instalación de Visual Studio, debe haber un editbin.exearchivo. Entonces, en mi instalación predeterminada, lo encuentro en

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

Para que el programa funcione, tal vez deba ejecutar vcvars32.batprimero en el mismo directorio. Entonces un

editbin /LARGEADDRESSAWARE <your compiled exe file>

es suficiente para que su programa utilice 4 GB de RAM. <your compiled exe file>es el exe, que VS generó al compilar su proyecto.

Si desea automatizar este comportamiento cada vez que compila su proyecto, use el siguiente evento Post-Build para el proyecto ejecutado:

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

Nota al margen: se puede hacer lo mismo con el devenv.exepara permitir que Visual Studio también use 4GB de RAM en lugar de 1.2GB (pero primero haga una copia de seguridad de la antigua devenv.exe).

Desty
fuente
Muchas gracias. Esto funciona para mi. Pero, ¿tenemos algún problema identificado después de aumentar el límite de memoria a 4 GB?
Maverick
28

Vale la pena mencionar que el valor predeterminado para una compilación 'Cualquier CPU' ahora marca la casilla de verificación 'Preferir 32 bits'. Al estar configurado en AnyCPU, en un sistema operativo de 64 bits con 16 gb de RAM aún puede alcanzar una excepción de memoria insuficiente en 2 gb si se marca esta opción.

Prefer32BitCheckBox

Tonycoupland
fuente
2
Esto resolvió absolutamente mis problemas de
falta
2

Parece que tiene un arco de 64 bits, bien, pero una versión de 32 bits del tiempo de ejecución de .NET y / o una versión de 32 bits de Windows.

Y como tal, el espacio de direcciones disponible para su proceso sigue siendo el mismo, no ha cambiado con respecto a su configuración anterior.

Actualice a un sistema operativo de 64 bits y una versión .NET de 64 bits;)

fge
fuente
1

¿Su aplicación se ejecuta como un proceso de 64 o 32 bits? Puede verificar esto en el administrador de tareas.

Podría ser, se está ejecutando como 32 bits, aunque todo el sistema se ejecuta en 64 bits.

Si es de 32 bits, una biblioteca de terceros podría estar causando esto. Pero primero asegúrese de que su aplicación se esté compilando para "Cualquier CPU", como se indica en los comentarios.

Jacco
fuente
0

Si tiene Windows de 32 bits, este método no funciona sin las siguientes configuraciones.

  1. Ejecute el indicador cmd.exe (importante: Ejecutar como administrador)
  2. escriba bcdedit.exe y ejecute
  3. Mire los parámetros de "aumento usuariova" y no hay, entonces escriba la siguiente declaración
  4. bcdedit / set aumentaruserva 3072
  5. y nuevamente el paso 2 y verifique los parámetros

Agregamos esta configuración y este bloque comenzó.

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

Más información: comando increaseuserva: https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/bcdedit--set

Mehmet Kurt
fuente