recommended microsoft management windows memory memory-management virtual-address-space

microsoft - virtual memory windows 10



¿Inconvenientes de usar/LARGEADDRESSAWARE para ejecutables de Windows de 32 bits? (3)

Necesitamos vincular uno de nuestros ejecutables con esta bandera ya que usa mucha memoria.
Pero ¿por qué darle un tratamiento EXE a un archivo EXE? ¿Por qué no estandarizar en / LARGEADDRESSAWARE?

Entonces, la pregunta es: ¿hay algún problema con el uso de / LARGEADDRESSAWARE incluso si no lo necesita? ¿Por qué no usarlo como estándar para todos los archivos EXE?


aplicando ciegamente la bandera de LargeAddressAware a su ejecutable de 32 bits ¡despliega una bomba de tiempo !

al establecer este indicador , está testificando al sistema operativo:

sí, mi aplicación (y todas las DLL que se cargan durante el tiempo de ejecución) pueden manejar direcciones de memoria de hasta 4 GB.
así que no restrinja el VAS para el proceso a 2 GB, pero desbloquee el rango completo (de 4 GB) ".

pero, ¿puedes realmente garantizar?
¿asume la responsabilidad de todos los archivos DLL del sistema, los redistribuibles de Microsoft y los módulos de terceros que pueda usar su proceso?

generalmente, la asignación de memoria devuelve direcciones virtuales en orden de bajo a alto. entonces, a menos que su proceso consuma mucha memoria (o tenga un espacio de direcciones virtuales muy fragmentado), nunca usará direcciones más allá del límite de 2 GB. esto está ocultando errores relacionados con direcciones altas.

si existen tales errores, son difíciles de identificar. esporádicamente aparecerán "tarde o temprano". Es solo cuestión de tiempo.

Afortunadamente, existe un interruptor extremadamente útil para todo el sistema integrado en el sistema operativo Windows:
para fines de prueba use la configuración de registro MEM_TOP_DOWN.
esto obliga a todas las asignaciones de memoria a ir de arriba hacia abajo, en lugar de hacia abajo.

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager/Memory Management] "AllocationPreference"=dword:00100000

(Esto es hex 0x100000. Requiere Windows reiniciar, por supuesto)

con este interruptor habilitado, identificará los problemas "antes" en lugar de "más tarde". lo ideal es que los veas "desde el principio".

nota al margen: para el primer análisis recomiendo encarecidamente la herramienta VMmap ( SysInternals ).

conclusiones:

Al aplicar el indicador LAA a su ejecutable de 32 bits, es obligatorio probarlo completamente en un sistema operativo x64 con el interruptor TopDown AllocationPreference establecido.

para problemas en su propio código , puede corregirlos.
solo para nombrar un ejemplo muy obvio: use enteros sin signo en lugar de enteros con signo para punteros de memoria.

cuando encuentre problemas con módulos de terceros , debe pedirle al autor que corrija sus errores. a menos que esto se haga, será mejor que elimines el indicador de LargeAddressAware de tu ejecutable.

una nota sobre la prueba:

el conmutador de registro MemTopDown no está logrando los resultados deseados para las pruebas unitarias que son ejecutadas por un "corredor de prueba" que no está habilitado para LAA.
ver: Pruebas unitarias para x86 LargeAddressAware compatibilidad

PD:
también muy "relacionado" y bastante interesante es la migración del código de 32 bits a 64 bits.
para ejemplos ver:


No, el "código heredado" en este contexto (C / C ++) no es exclusivamente un código que reproduce trucos feos con el MSB de punteros.

También incluye todo el código que usa ''int'' para almacenar la diferencia entre dos punteros, o la longitud de un área de memoria, en lugar de usar el tipo correcto ''size_t'': ''int'' firmado tiene 31 bits y no puede manejar un valor de más de 2 Gb.

Una forma de curar una buena parte de su código es revisarlo y corregir todas esas inocuas advertencias de "mezcla firmada y no firmada". Debería hacer una buena parte del trabajo, al menos si no ha definido la función donde un argumento de tipo int es realmente una longitud de memoria.

Sin embargo, ese "código heredado" probablemente funcione bien durante bastante tiempo, incluso si no corrige nada.

Solo se romperá cuando asigne más de 2 Gb en un bloque. O cuando comparas dos punteros no relacionados que están a más de 2 Gb de distancia el uno del otro.
Como la comparación de punteros no relacionados es técnicamente un comportamiento indefinido de todos modos, no encontrará tanto código que lo haga (pero nunca puede estar seguro).
Y con mucha frecuencia, incluso si en total necesita más de 2 Gb, su programa en realidad nunca realiza asignaciones únicas que son más grandes que eso. De hecho, en Windows, incluso con LARGEADDRESSAWARE, no podrá asignarlo de manera predeterminada dada la forma en que se organiza la memoria. Debería barajar la DLL del sistema para obtener un bloque continuo de más de 2 GB

Pero las leyes de Murphy dicen que ese tipo de código se romperá un día, es solo que pasará mucho tiempo después de que haya habilitado LARGEADDRESSAWARE sin verificarlo, y cuando nadie recuerde que esto se ha hecho.


Porque muchos códigos heredados se escriben con la expectativa de que los punteros "negativos" no sean válidos. Cualquier cosa en los dos primeros Gb de un proceso de 32 bits tiene configurado el msb.

Como tal, es mucho más fácil para Microsoft ir a lo seguro, y requiere aplicaciones que (a) necesitan que los 4Gb completos y (b) se hayan desarrollado y probado en un escenario de memoria grande, para simplemente establecer la bandera.

No es, como habrás notado, tan difícil.

Raymond Chen, en su blog The Old New Thing , cubre los problemas para encenderlo en todas las aplicaciones (de 32 bits).