1

In experimenting with reserving and committing virtual memory to a process, I allocated 64K bytes of memory with VirtualAlloc, memcpy'd a test string into it, printf'd it like a string, freed the memory with VirtualFree with the MEM_RELEASE flag, and printf'd it again. For some reason, no page fault is triggered. Why is this?

#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;
}

Output:

lpvPagedMemory = 0x00F00000
Before free: I love foxes \(^o^)/
After free:  I love foxes \(^o^)/
Mona the Monad
  • 2,265
  • 3
  • 19
  • 30
  • 2
    No where is it defined that accessing freed memory will cause a page fault. It *may* cause a page fault. But that's not a certainty. In C this is called Undefined Behaviour. Any code that has UB is considered to be buggy (even if some runs of the program do not exhibit obvious "bad" behaviour).This question has more details: [Undefined, unspecified and implementation-defined behavior](http://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) – kaylum Jul 25 '16 at 20:39
  • 2
    VirtualFree(lpvMem, 0, MEM_RELEASE); - this is correct code. VirtualFree(lpvMem, dwMemSize, MEM_RELEASE); - error - "If the dwFreeType parameter is MEM_RELEASE, this parameter must be 0" – RbMm Jul 25 '16 at 20:56
  • 2
    @kaylum It is a defined certainty **on Windows**. C does not define it but Windows does. – user253751 Jul 25 '16 at 20:59
  • @user3386109 - here nothing common with "Can a local variable's memory be accessed outside its scope?". here simply error by VirtualFree api call with wrong second parameter - must be 0 – RbMm Jul 25 '16 at 21:07
  • Voting to reopen as this is not a duplicate. – user253751 Jul 25 '16 at 21:07

1 Answers1

12

This line:

VirtualFree(lpvMem, dwMemSize, MEM_RELEASE);

is an error. You are not checking what VirtualFree() returns, and the documentation says:

dwSize [in]
...
If the dwFreeType parameter is MEM_RELEASE, this parameter must be 0 (zero). The function frees the entire region that is reserved in the initial allocation call to VirtualAlloc.

So you need to use this instead:

VirtualFree(lpvMem, 0, MEM_RELEASE);

About the page fault - it can (and must) only happen after a successful call to VirtualFree().

IInspectable
  • 46,945
  • 8
  • 85
  • 181
RbMm
  • 31,280
  • 3
  • 35
  • 56