The following program shows how you might implement a heap shared between a parent process and several child processes. The program consists of two parts. The first part shows the parent process, which creates the shared heap. The second part shows the child process started by a loop in the parent process.
Parent Process
The parent process creates the shared heap.
Sharing memory across processes in Windows/NT is accomplished by using Win32 File API's, using the system paging file as the shared file. If you wish to use the C library heap functions, you must also ensure that the memory to be shared is allocated at the same address in all processes which will be sharing the heap.
Child Process
The child process is started by the loop in the parent process.
/* User Heap - Parent Process */
#include <umalloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <winbase.h>
#define PAGING_FILE 0xFFFFFFFF
#define MEMORY_SIZE 65536
#define BASE_MEM (VOID*)0x01000000
static HANDLE hFile; /* Handle to memory file */
static void* hMap; /* Handle to allocated memory */
typedef struct mem_info {
void * pBase;
Heap_t pHeap;
} MEM_INFO_T;
/*------------------------------------------------------------------------*/
/* inithp: */
/* Function to create and open the heap with a named shared memory object */
/*------------------------------------------------------------------------*/
static Heap_t inithp(size_t heap_size)
{
MEM_INFO_T info; /* Info structure */
/* Allocate shared memory from the system by creating a shared memory */
/* pool basing it out of the system paging (swapper) file. */
hFile = CreateFileMapping( (HANDLE) PAGING_FILE,
NULL,
PAGE_READWRITE,
0,
heap_size + sizeof(Heap_t),
"MYNAME_SHAREMEM" );
if (hFile == NULL) {
return NULL;
}
/* Map the file to this process' address space, starting at an address */
/* that should also be available in child processe(s) */
hMap = MapViewOfFileEx( hFile, FILE_MAP_WRITE, 0, 0, 0, BASE_MEM );
info.pBase = hMap;
if (info.pBase == NULL) {
return NULL;
}
/* Create a fixed sized heap. Put the heap handle as well as the */
/* base heap address at the beginning of the shared memory. */
info.pHeap = _ucreate((char *)info.pBase + sizeof(info),
heap_size - sizeof(info),
!_BLOCK_CLEAN,
_HEAP_SHARED | _HEAP_REGULAR,
NULL, NULL);
if (info.pBase == NULL) {
return NULL;
}
memcpy(info.pBase, info, sizeof(info));
if (_uopen(info.pHeap)) { /* Open heap and check result */
return NULL;
}
return info.pHeap;
}
/*------------------------------------------------------------------------*/
/* termhp: */
/* Function to close and destroy the heap */
/*------------------------------------------------------------------------*/
static int termhp(Heap_t uheap)
{
if (_uclose(uheap)) /* close heap */
return 1;
if (_udestroy(uheap, _FORCE)) /* force destruction of heap */
return 1;
UnmapViewOfFile(hMap); /* return memory to system */
CloseHandle(hFile);
return 0;
}
/*------------------------------------------------------------------------*/
/* main: */
/* Main function to test creating, writing to and destroying a shared */
/* heap. */
/*------------------------------------------------------------------------*/
int main(void)
{
int i, rc; /* Index and return code */
Heap_t uheap; /* heap to create */
void *init_block; /* initial block to use */
char *p; /* for allocating from heap */
/* */
/* call init function to create and open the heap */
/* */
uheap = inithp(MEMORY_SIZE);
if (uheap == NULL) /* check for success */
return 1; /* if failure, return non zero */
/* */
/* perform operations on uheap */
/* */
for (i = 1; i <= 5; i++)
{
p = _umalloc(uheap, 10); /* allocate from uheap */
if (p == NULL)
return 1;
memset(p, 'M', _msize(p)); /* set all bytes in p to 'M' */
p = realloc(p,50); /* reallocate from uheap */
if (p == NULL)
return 1;
memset(p, 'R', _msize(p)); /* set all bytes in p to 'R' */
}
/* */
/* Start a second process which accesses the heap */
/* */
if (system("memshr2.exe"))
return 1;
/* */
/* Take a look at the memory that we just wrote to. Note that memshr.c */
/* and memshr2.c should have been compiled specifying the /Tm+ flag. */
/* */
#ifdef DEBUG
_udump_allocated(uheap, -1);
#endif
/* */
/* call term function to close and destroy the heap */
/* */
rc = termhp(uheap);
#ifdef DEBUG
printf("memshr ending... rc = %d\n", rc);
#endif
return rc;
}
/* User Heap - Child Process */
#include <umalloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <winbase.h>
static HANDLE hFile; /* Handle to memory file */
static void* hMap; /* Handle to allocated memory */
typedef struct mem_info {
void * pBase;
Heap_t pHeap;
} MEM_INFO_T;
/*------------------------------------------------------------------------*/
/* inithp: Subprocess Version */
/* Function to create and open the heap with a named shared memory object */
/*------------------------------------------------------------------------*/
static Heap_t inithp(void)
{
MEM_INFO_T info; /* Info structure */
/* Open the shared memory file by name. The file is based on the */
/* system paging (swapper) file. */
hFile = OpenFileMapping(FILE_MAP_WRITE, FALSE, "MYNAME_SHAREMEM");
if (hFile == NULL) {
return NULL;
}
/* Figure out where to map this file by looking at the address in the */
/* shared memory where the memory was mapped in the parent process. */
hMap = MapViewOfFile( hFile, FILE_MAP_WRITE, 0, 0, sizeof(info) );
if (hMap == NULL) {
return NULL;
}
/* Extract the heap and base memory address from shared memory */
memcpy(info, hMap, sizeof(info));
UnmapViewOfFile(hMap);
hMap = MapViewOfFileEx( hFile, FILE_MAP_WRITE, 0, 0, 0, info.pBase );
if (_uopen(info.pHeap)) { /* Open heap and check result */
return NULL;
}
return info.pHeap;
}
/*------------------------------------------------------------------------*/
/* termhp: */
/* Function to close my view of the heap */
/*------------------------------------------------------------------------*/
static int termhp(Heap_t uheap)
{
if (_uclose(uheap)) /* close heap */
return 1;
UnmapViewOfFile(hMap); /* return memory to system */
CloseHandle(hFile);
return 0;
}
/*------------------------------------------------------------------------*/
/* main: */
/* Main function to test creating, writing to and destroying a shared */
/* heap. */
/*------------------------------------------------------------------------*/
int main(void)
{
int rc, i; /* for return code, loop iteration */
Heap_t uheap, oldheap; /* heap to create, old default heap */
char *p; /* for allocating from the heap */
/* */
/* Get the heap storage from the shared memory */
/* */
uheap = inithp();
if (uheap == NULL)
return 1;
/* */
/* Register uheap as default run-time heap, save old default */
/* */
oldheap = _udefault(uheap);
if (oldheap == NULL) {
return termhp(uheap);
}
/* */
/* Perform operations on uheap */
/* */
for (i = 1; i <= 5; i++)
{
p = malloc(10); /* malloc uses default heap, which is now uheap*/
memset(p, 'M', _msize(p));
}
/* */
/* Replace original default heap and check result */
/* */
if (uheap != _udefault(oldheap)) {
return termhp(uheap);
}
/* */
/* Close my views of the heap */
/* */
rc = termhp(uheap);
#ifdef DEBUG
printf("Returning from memshr2 rc = %d\n", rc);
#endif
return rc;
}
![]()
Example of Creating and
Using a Heap