2016-07-25 2 views
1

En expérimentant avec la réservation et la validation de la mémoire virtuelle à un processus, j'ai alloué 64K octets de mémoire avec VirtualAlloc, memcpy 'une chaîne de test dedans, printf' d comme une chaîne, libéré la mémoire avec VirtualFree avec le drapeau MEM_RELEASE, et printf 'd encore. Pour une raison quelconque, aucune erreur de page n'est déclenchée. Pourquoi est-ce?La mémoire libérée ne provoquait pas de défaut de page

#include <stdio.h> 
#include <windows.h> 

INT main(DWORD argc, LPSTR argv[]) { 
    SYSTEM_INFO info; 
    DWORD dwPageSize; 
    DWORD dwMemSize; 
    LPVOID lpvMem; 

    GetSystemInfo(&info); 
    dwPageSize = info.dwPageSize; 
    dwMemSize = 16 * dwPageSize; 

    lpvMem = VirtualAlloc((LPVOID) 0x00F00000, dwMemSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 
    if (!lpvMem) { 
     printf("Error allocating virtual memory\n"); 
     return 1; 
    } 

    printf("lpvMem = 0x%08X\n", (UINT32) (UINT64) lpvMem); 

    if (!memcpy(lpvMem, "I love foxes \\(^o^)/", 21)) { 
     printf("Error copying memory (error code 0x%08X)\n", GetLastError()); 
     return 1; 
    } 

    printf("Before free: %s\n", (LPCSTR) lpvMem); 
    VirtualFree(lpvMem, dwMemSize, MEM_RELEASE); 
    printf("After free: %s\n", (LPCSTR) lpvMem); 

    fflush(stdout); 

    return 0; 
} 

sortie:

lpvPagedMemory = 0x00F00000 
Before free: I love foxes \(^o^)/ 
After free: I love foxes \(^o^)/ 
+2

Non où est-il défini que l'accès à la mémoire libérée provoquera une erreur de page. Il * peut * provoquer une erreur de page. Mais ce n'est pas une certitude. En C, cela s'appelle Undefined Behavior. Tout code qui a UB est considéré comme bogué (même si certaines exécutions du programme ne présentent pas un comportement "mauvais" évident). Cette question a plus de détails: [comportement indéfini, non spécifié et implémenté] (http: // stackoverflow .com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) – kaylum

+2

VirtualFree (lpvMem, 0, MEM_RELEASE); - C'est le code correct. VirtualFree (lpvMem, dwMemSize, MEM_RELEASE); - error - "Si le paramètre dwFreeType est MEM_RELEASE, ce paramètre doit être 0" – RbMm

+2

@kaylum Il s'agit d'une certitude définie ** sous Windows **. C ne le définit pas mais Windows le fait. – immibis

Répondre

10

Cette ligne:

VirtualFree(lpvMem, dwMemSize, MEM_RELEASE); 

est une erreur. Vous n'êtes pas vérifier ce VirtualFree() les retours, et la documentation Says:

dwSize [en]
...
Si le paramètre dwFreeType est MEM_RELEASE, ce paramètre doit être 0 (zéro). La fonction libère la région entière réservée dans l'appel d'allocation initial à VirtualAlloc.

Vous devez utiliser ceci:

VirtualFree(lpvMem, 0, MEM_RELEASE); 

A propos de la faute de page - il peut (et doit) ne se produira après un appel -VirtualFree().