Inconvenientes de usar / LARGEADDRESSAWARE para ejecutables de Windows de 32 bits?


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

Así que la pregunta es: ¿Hay algo malo con el uso de /LARGEADDRESSAWARE incluso si no lo necesita. ¿Por qué no usarlo como estándar para todos los archivos EXE?

Author: Arve, 2010-02-18

3 answers

Aplicando ciegamente la bandera LargeAddressAware a su ejecutable de 32 bits despliega una bomba de tiempo marcando!

Poniendo esta bandera usted está testificando al OS:

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

Pero ¿puedes realmente garantizar?
¿asumes la responsabilidad de todos los DLLS del sistema, redistribuibles de Microsoft y módulos de terceros que su proceso puede utilizar?

Normalmente, la asignación de memoria devuelve direcciones virtuales en orden bajo a alto. por lo tanto, 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 es ocultar errores relacionados con direcciones altas.

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

Afortunadamente, hay un interruptor muy práctico para todo el sistema integrado en el sistema operativo Windows:
para fines de prueba, use la configuración del registro MEM_TOP_DOWN.
esto obliga a todas las asignaciones de memoria a ir de arriba hacia abajo, en lugar de la normal de abajo hacia arriba.

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

(esto es hex 0x100000. requiere reiniciar Windows, por supuesto)

Con este interruptor habilitado, identificará los problemas "antes" en lugar de "más tarde". lo ideal es que los veas " desde 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 conmutador TopDown AllocationPreference establecido.

Para problemas en su propio código puede ser capaz de solucionarlos.
solo para nombrar un ejemplo muy obvio: use enteros sin signo en lugar de enteros con signo para la memoria puntero.

Cuando encuentre problemas con los módulos de 3rd-party, debe pedirle al autor que corrija sus errores. a menos que esto se hace es mejor eliminar la bandera LargeAddressAware de su ejecutable.


Una nota sobre las pruebas:

El conmutador de registro MemTopDown no está logrando los resultados deseados para pruebas unitarias que son ejecutadas por un "corredor de pruebas" que a su vez es no LAA habilitado.
ver: Pruebas unitarias para x86 LargeAddressAware compatibilidad


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

 39
Author: Opmet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:04

Porque gran parte del código heredado se escribe con la expectativa de que los punteros "negativos" no son válidos. Cualquier cosa en los dos primeros Gb de un proceso de 32 bits tiene el conjunto de msb.

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

No es - como has notado - tan difícil.

Raymond Chen - en su blog La Vieja Cosa Nueva - cubre los problemas al encenderlo para todas las aplicaciones (de 32 bits).

 10
Author: Chris Becke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-05 12:37:25

No, "código heredado" en este contexto (C/C++) no es exclusivamente código que juega malas jugadas 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 tu código es repasarlo y corregir todos de aquellos inocuo "mezcla de advertencias firmadas y sin firmar". 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 aparentemente funcionará bien durante bastante tiempo, incluso si no corrige nada.

Solo se romperá cuando asigne más de 2 Gb en un bloque. O cuando compare dos punteros no relacionados que están a más de 2 Gb de distancia de cada uno otro.
Como comparar punteros no relacionados es técnicamente un comportamiento indefinido de todos modos, no encontrará mucho 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 hace asignaciones individuales que sean más grandes que eso. De hecho, en Windows, incluso con LARGEADDRESSAWARE no podrá asignar esa cantidad por defecto dada la forma en que se organiza la memoria. Tendrías que barajar el DLL del sistema para obtener un bloque continuo de más de 2Gb

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

 5
Author: jmd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-23 17:52:23