win32 Memory Management

The GlobalAlloc() and LocalAlloc() functions should not be used, but they are available in the win32 API. Back in the 16 bit days, a long long time ago in a galaxy far, far away, these functions determined what sort of memory segments were used. Nowadays, the local heap and the global heap are not distinguished, rendering GlobalAlloc() and LocalAlloc() the same. In fact, GlobalAlloc() and LocalAlloc() are just wrappers for the HeapAlloc() function.

The GlobalAlloc() function allocates a block of memory from the heap. Memory allocated with GlobalAlloc() is always read-write. The GlobalAlloc() function takes two arguments. The first argument is a one of five possible flags.The GHND flag is a combination of the GMEM_MOVEABLE and the GMEM_ZEROINIT flags. The GMEM_MOVEABLE flag allocates moveable memory. This flag cannot be combined with the GMEM_FIXED flag, which allocates fixed memory. The GMEM_FIXED flag returns a pointer value to the memory block. To access this memory, cast the return value as a pointer. The GMEM_ZEROINIT flag initializes the memory contents to 0. The GPTR flag is a combination of the GMEM_FIXED and the GMEM_ZEROINIT flags.

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

int _tmain(int argc, _TCHAR* argv[])
{
    printf("GHND = %d\n", GHND);
    //equal to GHND
    printf("GMEM_MOVEABLE | GMEM_ZEROINIT = %d\n", GMEM_MOVEABLE | GMEM_ZEROINIT);
    printf("GMEM_MOVEABLE = %d\n", GMEM_MOVEABLE);
    printf("GMEM_FIXED = %d\n", GMEM_FIXED);
    printf("GMEM_ZEROINIT = %d\n", GMEM_ZEROINIT);
    printf("GPTR = %d\n", GPTR);

    return 0;
}

The GlobalAlloc() function returns the handle to the allocated memory object, HGLOBAL, if successful; otherwise, it returns NULL.

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

int _tmain(int argc, _TCHAR* argv[])
{
    //moveable memory
    HGLOBAL hG = GlobalAlloc(GHND, 256);

    //returns NULL if it did not work
    if(hG==NULL){
        printf("Memory was not allocated.\n");
    } else {
        printf("Memory was allocated.\n");
    }

    return 0;
}

In order to cast the HGLOBAL handle to a pointer we can use, we must first lock the memory using the GlobalLock() function. The GlobalLock() function locks a global memory object and returns a pointer to the first byte of the object’s memory block. The locked memory block then cannot be moved or thrown away.

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

int _tmain(int argc, _TCHAR* argv[])
{
    //moveable memory
    SYSTEM_INFO *structPtrSI;

    //equivalent of GHND
    HGLOBAL hG = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(SYSTEM_INFO));

    if(hG!=NULL){
        printf("Memory allocated!\n");
    }

    structPtrSI = (SYSTEM_INFO*)GlobalLock(hG);

    //NULL if there is a problem
    if(structPtrSI!=NULL){
        printf("Memory is locked.\n");
    }

    return 0;
}

Remember, the GlobalLock() function must be used to obtain a pointer to a memory object allocated with the GlobalAlloc() function with the GMEM_MOVEABLE flag.

To avoid having to lock the memory with GlobalLock(), we could instead pass in the GMEM_FIXED flag instead of GMEM_MOVEABLE.

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

int _tmain(int argc, _TCHAR* argv[])
{
    
    TAPE_GET_DRIVE_PARAMETERS *structTDParams = 
        (TAPE_GET_DRIVE_PARAMETERS*)GlobalAlloc(GMEM_FIXED, sizeof(TAPE_GET_DRIVE_PARAMETERS));

    if(structTDParams!=NULL){
        printf("Structure allocated.\n");
    }

    return 0;
}

The GlobalFree() function frees a global memory object and invalidates its handle. Freeing a memory block returns the memory to the operating system so it can be reused. All memory blocks allocated within an application ought to be freed before the application exits.

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

int _tmain(int argc, _TCHAR* argv[])
{
    int *iPtr = NULL;
    HGLOBAL hMovMem = GlobalAlloc(GHND, 256);
    HGLOBAL hFixedMem = GlobalAlloc(GPTR, sizeof(INT));

    if(hMovMem && hFixedMem != NULL){
        printf("Memory allocated.\n");
    }

    iPtr = (int *)hFixedMem;

    *iPtr = 73;

    printf("%d\n", *iPtr);

    iPtr = NULL;

    if((GlobalFree(hFixedMem))==NULL){
        printf("Fixed heap memory freed.\n");
    }

    if((GlobalFree(hMovMem))==NULL){
        printf("Moveable heap memory freed.\n");
    }
    return 0;
}

Remember, there should be a matching call to GlobalFree() for every call to GlobalAlloc().

Interested in learning standard C? Check out http://www.amazon.com/Big-Als-C-Standard-ebook/dp/B00A4JGE0M/.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s