Tengo una aplicación Visual Studio 2008 C++ para Windows Mobile 6.x donde estoy contando la cantidad de memoria virtual libre disponible para un proceso determinado. (Me di cuenta de que no está tomando la fragmentación en cuenta.) Mi código es básicamente lo siguiente:Explicar una línea de complementos de dos matemática contar memoria virtual libre
MEMORY_BASIC_INFORMATION mbi = { 0 };
/// total free memory available to the process
DWORD free = 0;
/// base memory address for the given process index (2-33).
DWORD slot_base_addr = process_index * 0x02000000;
/// look at each memory region for the process.
for(DWORD offset = 0x10000;
offset < 0x02000000;
offset += mbi.RegionSize)
{
::VirtualQuery((void*)(slot_base_addr + offset),
&mbi,
sizeof(MEMORY_BASIC_INFORMATION));
if(mbi.State == MEM_FREE)
{
free += (mbi.RegionSize - ((~(DWORD)mbi.BaseAddress + 1) & 0xffff)) & 0xffff0000;
}
}
NKDbgPrintfW(L"%d bytes free\r\n", free);
puedo confirmar con otras APIs que esto parece funcionar perfectamente. Mi pregunta es ¿qué está haciendo esta línea:
free += (mbi.RegionSize - ((~(DWORD)mbi.BaseAddress + 1) & 0xffff)) & 0xffff0000;
¿Por qué es esto, no sólo:
free += mbi.RegionSize;
me encontré con la antigua línea en un poste Usenet por empleado MSFT Ross Jordan.
Gracias, PaulH
Editar:
Por ejemplo. Para la ranura 2 del proceso, esta es una lista de cada bloque de memoria libre con la cantidad de memoria gratuita proporcionada por el algoritmo Ross Jordan (RS) y solo el RegionSize (RS).
Slot: 2. Range: 0x04000000 - 0x06000000
RS: 16,384 bytes RJ: 0 bytes diff: 16384
RS: 4,096 bytes RJ: 0 bytes diff: 4096
RS: 4,096 bytes RJ: 0 bytes diff: 4096
RS: 4,096 bytes RJ: 0 bytes diff: 4096
RS: 4,096 bytes RJ: 0 bytes diff: 4096
RS: 4,096 bytes RJ: 0 bytes diff: 4096
RS: 36,864 bytes RJ: 0 bytes diff: 36864
RS: 65,536 bytes RJ: 65,536 bytes diff: 0
RS: 53,248 bytes RJ: 0 bytes diff: 53248
RS: 4,096 bytes RJ: 0 bytes diff: 4096
RS: 4,096 bytes RJ: 0 bytes diff: 4096
RS: 4,096 bytes RJ: 0 bytes diff: 4096
RS: 4,096 bytes RJ: 0 bytes diff: 4096
RS: 4,096 bytes RJ: 0 bytes diff: 4096
RS: 7,671,808 bytes RJ: 7,667,712 bytes diff: 4096
RS: 1,921,024 bytes RJ: 1,900,544 bytes diff: 20480
RS: 7,491,584 bytes RJ: 7,471,104 bytes diff: 20480
RS: 3,252,224 bytes RJ: 3,211,264 bytes diff: 40960
RS: 262,144 bytes RJ: 262,144 bytes diff: 0
RS: Total VM Free: 20,811,776 bytes.
RJ: Total VM Free: 20,578,304 bytes.
Edición 2:
Hans me llevó a la respuesta. Es solo una forma elegante de hacerlo, pero suponiendo que el tamaño de la asignación es de 64 KB.
SYSTEM_INFO si = { 0 };
::GetSystemInfo(&si);
free += mbi.RegionSize - mbi.RegionSize % si.dwAllocationGranularity;
Algo allí es importante. La memoria disponible para el 'proceso actual' dada por ese algoritmo coincide con lo que 'GlobalMemoryStatus()' dice que es. Si simplemente uso 'RegionSize', el resultado es consistentemente más pequeño en un par de docenas de KB. Como referencia, mi dwAllocationGranularity es de 64 KB. – PaulH
Erm, ¿cómo es eso posible? La declaración * resta * del Tamaño de la Región. Solo puede hacerlo más pequeño, no más grande. Si te gusta GlobalMemoryStatus, tal vez deberías usar eso. –
+1, Windows Mobile es bastante probable que sea uno de los "otros accesorios de hardware" –