Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

tMemSection Class: Keep track of thousands of pointers (Dynamic Memory Allocation)

4.75/5 (11 votes)
21 Jul 2009CPOL15 min read 28.1K   398  
Demonstrates how to group and organize memory blocks by using a couple of classes.
tms_demo

Introduction

Dynamic memory allocation is a need in professional C++ applications. However, such practice is a bit error-prone because many times developer may forget that free, HeapFree or delete call to free previously allocated memory.

In this article I m going to introduce two classes to help you to manage hundreds or thousands of memory blocks : tMemSegment and tMemSection

tMemSection encapsulates the multiple heap concept supported by Windows OS. It offers:

  • Dynamic Memory Allocation by using Win32 Heap Functions.
  • Group and sort memory blocks by unique IDs.
  • Multi-thread support: class members are thread safe.

tMemSegment is nothing more than a container of tMemSections objects. You can group and sort many tMemSections objects.

Contents

1. Heaps on Windows and tlw_memory.h overview

Each process running on Windows has a default heap provided by the system - also called process heap. Any process allocates memory dynamically from its own process heap. Windows allows developer to create extra heaps to improve process performance by using Heap Functions. Each extra heap is a section of one or more pages in the address space of the calling process.

So, each instance of tMemSection class corresponds to a new heap to the process.

All functionality of tMemSection is into tlw_memory.h. That means you should only #include it in your Win32 or MFC projects to start using it. The following table shows the contents (classes and types) of tlw_memory.h and a brief description of them.

TypeWhat is it
tMemExceptionCodeEnum for all available exception codes used by tMemSection and tMemSegment.
tMemExceptionException object raised by member functions.
tSyncObjSimple object that provides synchronization. It is used by instances of tMemSection/tMemSegment to guarantee thread safe access. 
tMemPtrType that represents pointer information.
tMemPtrIDType used to create memory block ID.
tMemSectionClass that handles dynamic memory usage.
tMemSegmentClass that implements a container of tMemSection objects.

1.1 Avoiding MFC compilation errors when using tlw_memory.h

You will notice tMemSection and tMemSegment use STL map and set types to group and sort pointer information. If you ever tried to use STL with MFC you probably faced some ugly compilation errors. 

Well, I had to deal with an annoying error when trying to compile my SampleApp in debug mode:

c:\program files\microsoft visual studio 8\vc\include\xtree(1317) : error C2061: syntax error : identifier '_Wherenode'

Error C2061 happened to me every time I switched to Debug configuration. It took some time until I realized the error cause is a #define:

C++
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

DEBUG_NEW is part of MFC debugging arsenal. It redefines new operator and that causes problems when using STL. Then, the simple solution is:

C++
#include "..\shared\tlw_memory.h"  // include always before DEBUG_NEW

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//#include "..\shared\tlw_memory.h"  // Ops! Wrong place ...

So, remember to include tlw_memory.h before DEBUG_NEW definition to avoid problems. Ok?

2. What does SampleApp do?

SampleApp (Figure 1) uses some features from tMemSection and tMemSegment classes. Its purpose is to demonstrate how to use multiple heaps (or sections) to improve applications performance or, at least, keep source code cleaner.

 SampleApp is run in two steps:

  • Step 1: Read all files in the path selected by user and saves file information in two sections (or heaps). Memory information is shown at List 1. 
  • Step 2: Transfer all information previously saved in those two sections to List 2. 

Take a look at Globals.h

C++
using namespace TLibWin;

#define MEM_TMP_DATA  10
#define MEM_FILE_INFO 20
#define MEM_FILE_PATH 30

extern tMemSegment vg_memory;

tMemSection and tMemSegment are into TLibWin namespace. So, you should always type using namespace TLibWin before get access to them.

Those three defines are IDs to name and sort tMemSections into tMemSegment container.

Now take a look at SampleAppDlg.cpp at function CSampleAppDlg::OnInitDialog

C++
vg_memory.Add(MEM_TMP_DATA, tMemSection());  // temporary data - general use
vg_memory.Add(MEM_FILE_INFO, tMemSection()); // keep WIN32_FIND_DATA struct for files
vg_memory.Add(MEM_FILE_PATH, tMemSection()); // keep path for files

You see three tMemSection objects being instantiated. The first argument in Add function specifies an ID to access those tMemSection objects.

You can explore the rest of SampleApp source code by yourself while reading the next part of this article that describes tMemSection and tMemSegment operations.

Note: SampleApp can scan an entire partition but if you are not logged in with administrative privileges some folders may not be accessible for reading (for instance, System32 folder). In that case, inaccessible folders will not be scanned.

3. tMemSection Class Members

tMemSection is responsible for allocating/freeing memory blocks keeping all pointers in a container. Those pointers might or not be sorted by an ID.

3.1 Construction/Destruction

tMemSection() 

    tMemSection constructs a new object. Each object tMemSection is associated a one heap.

~tMemSection()     

    Free all allocated memory and destroys extra heap. 

Parameters

    None.

Return

    If construction succeeds a new instance of tMemSection is returned.

    Otherwise a tMemException(tcErrorCantCreateNewSection) object exception is raised.

Sample Code

C++
using namespace TLibWin; // Do not forget this

...

// Two extra heaps are created
try
{
   tMemSection sec1; // new heap with initial size = MEM_SECTION_SIZE
   tMemSection *sec2 = new tMemSection(); // new heap with
                                          // initial size = MEM_SECTION_SIZE
} catch ( tMemException e )
{
   printf( "\nException while creating tMemSection object. code = %ld / system = %ld\n",
      e.ecode, e.sys_error );
}

Remarks

    MEM_SECTION_SIZE defines the initial value of the heap - 1 Megabyte by default. New heap is set to grow according to memory allocations. 

 See also:

    AllocAllocAndSet

3.2 tMemSection::Alloc

LPVOID Alloc(DWORD _size, tMemPtrID _id = tMemPtrID(tcNoId))

    Allocates _size bytes of memory.

Parameters

 

ParameterMeaning
_size   [in, required]Number of bytes to be allocated.
_id   [in, optional]An unique ID type tMemPtrID to name memory block. By setting an ID allows you not to save returned memory block pointer and retrieve that pointer any time by informing ID. tMemSection::tcNoId means no ID is passed.

Return

    If call succeeds a new pointer to memory block is returned.

    Otherwise one of these two exceptions can be raised depend upon result of call:

  • tMemException(tcErrorCantAllocateMemory): if allocations fails.
  • tMemException(tcErrorPointerIDAlreadyExists): if a duplicated ID is passed.

Sample Code

C++
try
{
   tMemSection sec1; // new heap with initial size = MEM_SECTION_SIZE

   ...

   LPVOID ptr1 = sec1.Alloc(1024); // Getting an unamed pointer
   LPVOID ptr2 = sec1.Alloc(1024, tMemPtrID(1)); // Getting a named pointer

   ...

} catch ( tMemException e )
{
   printf( "\nException! code = %ld / system = %ld\n",
      e.ecode, e.sys_error );
}

Remarks

    The _size is rounded up to a multiple of MEM_CHUNK to minimize fragmentation. 

See also:

    Free, Ptr, PtrSize

3.3 tMemSection::AllocAndSet

LPVOID AllocAndSet(DWORD _size, LPVOID _data, DWORD _data_size, tMemPtrID _id = tMemPtrID(tcNoId))

    Allocates _size bytes of memory and copy _data to it.

Parameters

 

ParameterMeaning
_size   [in, required]Number of bytes to be allocated.
_data [in, required]Buffer to be copied.
_data_size [in, required]Size of _data.
_id   [in, optional]An unique ID type tMemPtrID to name memory block. By setting an ID allows you not to save returned memory block pointer and retrieve that pointer any time by informing ID. tMemSection::tcNoId means no ID is passed.

Return

    If call succeeds a new pointer set with _data is returned.

    Otherwise one of these three exceptions can be raised depend upon result of call:

  • tMemException(tcErrorCantAllocateMemory): if allocations fails.
  • tMemException(tcErrorPointerIDAlreadyExists): if a duplicated ID is passed.
  • tMemException(tcErrorInvalidArgument): if _data is NULL or _data_size is 0.

Sample Code

C++
try
{
   tMemSection sec1;

   LPVOID ptr1 = sec1.Alloc(30);
   // Not thread safe
   memcpy( ptr1, "this is a test", sizeof("this is a test"));

   // Thread safe operation
   // Getting a named pointer
   LPVOID ptr2 = sec1.AllocAndSet(30, "this is a test", sizeof("this is a test"));
} catch ( tMemException e )
{
   printf( "\nException! code = %ld / system = %ld\n",
      e.ecode, e.sys_error );
}

Remarks

    The _size is rounded up to a multiple of MEM_CHUNK to minimize fragmentation. 

    If _data_size > _size then the memory block size is _data_size.

See also:

    Free, Ptr, PtrSize, Set, SetAt

 

3.4 tMemSection::Count

DWORD Count(void)

    Retrieves the number of memory blocks currently allocated.

Parameters

    None.

Return

    Number of memory blocks.

Sample Code

C++
DWORD total = sec.Count();

See also:

    TotalSize

 

3.5 tMemSection::FirstPtr

BOOL FirstPtr(tMemPtr &_ptr)

    Starts memory block enumeration.

Parameters

 

ParameterMeaning
tMemPtr   [out, required]or tMemSection::tPointer. Structure containing pointer information.

Return

    TRUE if there is, at least,  one memory block allocated and the corresponding tMemPtr information.

    Otherwise FALSE is returned.

Sample Code

C++
tMemPtr pointer;
if ( sec1.FirstPtr(pointer) )
do
{

   if ( pointer.user_size < 64 )
      sec1.Grow( LPVOID(pointer.ptr), 64 - pointer.user_size );

} while ( sec1.NextPtr(pointer) );

Remarks

        FirstPtr and NextPtr is a way to access pointers information when you do not have any other information - neither pointer nor ID. In fact, may be you never use them. You must use this member function together with NextPtr.

See also:

    NextPtr

3.6 tMemSection::Free

void Free(LPVOID _ptr)

void Free(tMemPtrID _id)

    Frees a memory block allocated previously by Alloc and AllocAndSet member functions.

Parameters

 

ParameterMeaning
_ptr   [in, required]Pointer to memory block returned by Alloc or AllocAndSet.
_id   [in, required]ID that names a memory block.

Return

    None.

Sample Code

C++
tMemSection sec;

LPVOID ptr = sec.Alloc(1000);
LPVOID ptr2 = sec.Alloc(300, tMemPtrID(1)); // Allocates for further use

...

sec.Free(ptr);
sec.Free(tMemPtrID(1)); // or sec.Free(ptr2)

 See also:

    AllocAllocAndSet, FreeAll

 

3.7 tMemSection::FreeAll

void FreeAll(BOOL _bFreeAtOnce = FALSE)

    Frees all allocated memory blocks.

Parameters

 

ParameterMeaning
_bFreeAtOnce    [in, optional]When TRUE HeapDestroy is called without calling HeapFree. Old hep is destroyed and a new HEAP is created during operation. When FALSE memory blocks are freed one by one by using HeapFree.

Return

    None.

Sample Code

C++
tMemSection sec1;
tMemSection sec2;

...

sec1.FreeAll(); // Free all memory blocks one by one
sec2.FreeAll(TRUE); // Free all memory blocks at once

Remarks

    Destructor calls FreeAll(TRUE) to improve performance. Heap API allows you call HeapDestroy without calling HeapFree function.

 See also:

    AllocAllocAndSet, Free

3.8 tMemSection::Get and GetAt

LPVOID Get(tMemPtrID _id, LPVOID _ret_data, DWORD _ret_data_size)

LPVOID GetAt(tMemPtrID _id, DWORD _at, LPVOID _ret_data, DWORD _ret_data_size)

    Retrieves data from a named memory block.

Parameters

ParameterMeaning
_id   [in, required]ID that names a memory block.
_at  [in, required]Byte position into memory block.
_ret_data   [out, required]Pointer to a buffer that receives data from memory block.
_ret_data_size   [in, required]Size of _ret_data buffer.

Return

    If call succeeds _ret_data is filled and a pointer to memory block referenced by _id is returned.

    Otherwise one of these three exceptions can be raised depend upon result of call:

  • tMemException(tcErrorPointerNotFound): if _id does not exist.
  • tMemException(tcErrorInvalidArgument): if _ret_data is not valid or _ret_data_size is 0.
  • tMemException(tcErrorOutOfRange): if _ret_data_size or _at+_ret_data_size is greater than size of memory block.

Sample Code

 

C++
// *** Producer -> Consumer Sample
#include "stdafx.h"

#include "tlw_memory.h"

using namespace TLibWin;

typedef struct __DATA
{
   long count;
   BOOL  count_set;
} TDATA;

tMemSection mem;

DWORD WINAPI ThreadProducer(void)
{
   TDATA reg;

   while ( TRUE )
   {
      try
      {
         mem.Get( tMemPtrID(1), &reg, sizeof(reg) );
         if ( !reg.count_set )
         {
            reg.count_set = TRUE;
            reg.count++;
            mem.Set( tMemPtrID(1), &reg, sizeof(reg) );   
         }
      } catch ( tMemException e )
      {
         _tprintf( _T("\nProducer Exception (%ld) ... Aborting ...\n"), e.ecode );
         exit(0);
      }
   }

   return 0;
}

DWORD WINAPI ThreadConsumer(void)
{
   TDATA reg;

   while ( TRUE )
   {
      try
      {
         mem.Get( tMemPtrID(1), &reg, sizeof(reg) );
         if ( reg.count_set )
         {
            reg.count_set = FALSE;
            reg.count--;
            mem.Set( tMemPtrID(1), &reg, sizeof(reg) );   
         }
      } catch ( tMemException e )
      {
         _tprintf( _T("\nConsumer Exception (%ld) ... Aborting ...\n"), e.ecode );
         exit(0);
      }
   }

   return 0;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
   TDATA reg = {0, FALSE };

   mem.AllocAndSet( sizeof(TDATA), &reg, sizeof(reg), tMemPtrID(1) );

   ::CreateThread( NULL, 0L, (LPTHREAD_START_ROUTINE)ThreadProducer, NULL, 0L, NULL );
   ::CreateThread( NULL, 0L, (LPTHREAD_START_ROUTINE)ThreadProducer, NULL, 0L, NULL );
   ::CreateThread( NULL, 0L, (LPTHREAD_START_ROUTINE)ThreadConsumer, NULL, 0L, NULL );
   ::CreateThread( NULL, 0L, (LPTHREAD_START_ROUTINE)ThreadConsumer, NULL, 0L, NULL );

   while ( TRUE )
   {
      mem.Get( tMemPtrID(1), &reg, sizeof(reg) );
      _tprintf(_T("\nCount = %ld"), reg.count );
      ::Sleep(250); 
   }

	return 0;
}

Remarks

        The sample code shows a producer consumer application. In the output Count must be 0 or 1 only.

        Use Get/GetAt and Set/SetAt to have synchronization when running a multi-thread applications. Memory blocks must be named to use these member functions.

 See also:

    Set, SetAt, AllocAllocAndSet

 

3.9 tMemSection::Grow

LPVOID Grow(LPVOID _ptr, DWORD _bytes)

LPVOID Grow(tMemPtrID _id, DWORD _bytes)

    Increases N _bytes of a memory block. 

Parameters

 

ParameterMeaning
_ptr   [in, required]Pointer to memory block returned by Alloc or AllocAndSet.
_id   [in, required]ID that names a memory block.
_bytes [in, required]Number of bytes to increase memory block.

Return

    If call succeeds a pointer to the memory block is returned.

    Otherwise one of these two exceptions can be raised depend upon result of call:

  • tMemException(tcErrorPointerNotFound): if _id or _ptr does not exist.
  • tMemException(tcErrorCantAllocateMemory): if allocation fails.

Sample Code

 

C++
tMemSection sec;
char *buf = (char *)sec.Alloc(128);
DWORD sz = 0;
while ( (sz = strlen(buf)) < 4096 )
{
   memset( &buf[sz], 'A', 127 );
   buf = (char *)sec.Grow(buf, 128);
   printf( "\nTotal Chars  = %ld", strlen(buf) );
}

Remarks

     The original memory block contents is preserved after size increasing.

     New memory block size is also rounded up to MEM_CHUNK to minimize fragmentation. 

See also:

    AllocAllocAndSet

3.10 tMemSection::NextPtr

 BOOL NextPtr(tMemPtr &_ptr)

    Continues pointer enumeration.

Parameters

 

ParameterMeaning
tMemPtr   [out, required]or tMemSection::tPointer. Structure containing pointer information.

Return

    TRUE if there is at least two memory blocks and the corresponding tMemPtr information.

    Otherwise FALSE is returned.

Sample Code

C++
tMemPtr pointer;
if ( sec1.FirstPtr(pointer) )
do
{

   if ( pointer.user_size < 64 )
      sec1.Grow( LPVOID(pointer.ptr), 64 - pointer.user_size );

} while ( sec1.NextPtr(pointer) );

Remarks

    FirstPtr and NextPtr is a way to access pointers information when you do not have any other information - neither pointer nor ID. In fact, may be you never use them. You must use this member function together with FirstPtr.

See also:

    FirstPtr

 

3.11 tMemSection::Ptr

 LPVOID Ptr(tMemPtrID _id)

    Retrieves pointer to a memory block by ID.

Parameters

 

ParameterMeaning
_id   [in, required]ID that names a memory block.

Return

    If ID exists then a pointer for a memory block is returned.

    Otherwise NULL is returned.

Sample Code

C++
#define MAIN_BUFFER 0x10

tMemSection g_sec;

void init(void)
{
   g_sec.Alloc(16*1024, tMemPtrID(MAIN_BUFFER)); // Allocates buffer
   ...
}

...

void SendBuffer(void)
{
   // Retrieves pointer to memory block by ID
   BYTE *buf = (BYTE *)g_sec.Ptr(tMemPtrID(MAIN_BUFFER));
   ....
}

Remarks

        Name a memory block gives you more flexibility because you do not have to worry in saving the pointer.

 See also:

    AllocAllocAndSet

 

3.12 tMemSection::PtrSize

DWORD PtrSize(LPVOID _ptr, DWORD *_sys_size = NULL)

    Retrieves both memory block sizes: user defined and system defined (MEM_CHUNK size rounded) .

Parameters

 

ParameterMeaning
_ptr   [in, required]Pointer to memory block returned by Alloc or AllocAndSet.
__sys_size   [out, optional]Returned the real allocated size of memory block (MEM_CHUNK size rounded) .

Return

 

    If call succeeds size of memory block is returned. If _sys_size is not NULL then the real size of the block that is rounded up to a multiple of MEM_CHUNK is returned too.

    Otherwise 0 is returned.

Sample Code

 
C++
tMemSection sec;
DWORD sz1 = 0, sz2 = 0;

char *buf = (char *)sec.Alloc(1700);

sz1 = sec.PtrSize(buf, &sz2);

buf = (char *)sec.Grow(buf,1024);

sz1 = sec.PtrSize(buf, &sz2);

Remarks

    tMemSection allocates size bytes requested by user. However, to minimize fragmentation, size is rounded up to a multiple of MEM_CHUNK.

 See also:

    TotalSize

3.13 tMemSection::Set and SetAt

LPVOID Set(tMemPtrID _id, LPVOID _data, DWORD _data_size)

LPVOID SetAt(tMemPtrID _id, DWORD _at, LPVOID _data, DWORD _data_size)

    Set data to a named memory block.

Parameters

ParameterMeaning
_id   [in, required]ID that names a memory block.
_at  [in, required]Byte position into memory block.
_data   [out, required]Pointer to a buffer to set memory block.
_data_size   [in, required]Size of _data buffer.

Return

    If call succeeds a pointer to memory block referenced by _id is returned.

    Otherwise one of these three exceptions can be raised depend upon result of call:

  • tMemException(tcErrorPointerNotFound): if _id does not exist.
  • tMemException(tcErrorInvalidArgument): if _data is not valid or _data_size is 0.
  • tMemException(tcErrorOutOfRange): if _data_size or _at+_data_size is greater than size of memory block.

Sample Code

 

    See Get/GetAt sample code.

See also:

    Get, GetAt

 

3.14 tMemSection::TotalSize

DWORD TotalSize(DWORD *_sys_size = NULL)

    Retrieves total memory allocated by a tMemSection object.

Parameters

 

ParameterMeaning
_sys_size   [out, optional]Returned the real allocated size of memory (MEM_CHUNK size rounded).

Return

 

    If call succeeds total size of allocated memory is returned. If _sys_size is not NULL then the real size of total memory that is rounded up to a multiple of MEM_CHUNK is returned too.

    Otherwise 0 is returned.

Sample Code

 
C++
tMemSection sec;
DWORD sz1 = 0, sz2 = 0;

char *buf1 = (char *)sec.Alloc(1700);
char *buf2 = (char *)sec.Alloc(1300);

sz1 = sec.TotalSize(&sz2);

Remarks

     TotalSize returns the sum of all memory blocks sizes.

 See also:

    PtrSize

3.15 tMemSection::operator=

    operator= copies all memory blocks to another  tMemSection object.  

Sample Code

 
C++
tMemSection sec_src;
tMemSection sec_tar;

sec_src.AllocAndSet( 30, "pointer 1", sizeof("pointer 1") );
sec_src.AllocAndSet( 30, "pointer 2", sizeof("pointer 2"), tMemPtrID(1) );

printf( "\n sec_src has %ld memory blocks.", sec_src.Count() );
printf( "\n sec_tar has %ld memory blocks.", sec_tar.Count() );

sec_tar = sec_src;

sec_src.FreeAll();

printf( "\n\n sec_src has %ld memory blocks.", sec_src.Count() );
printf( "\n sec_tar has %ld memory blocks.", sec_tar.Count() );

Remarks

 

    The result of operator= is a target object that contains the same number of memory blocks with the same contents in a different heap. The sample code output is:

Image 2

Figure 2 - Sample code output

 

4. tMemSegment Class Members

    tMemSegment class provides a container from 1 to N tMemSection objects. tMemSection objects are sorted by a DWORD value.

 

4.1 Construction/Destruction

tMemSegment() 

    tMemSegment constructs a new object.

~tMemSegment()     

    Destroys all tMemSection objects and free all memory.

Parameters

    None.

Return

    A new instance of tMemSegment.

Sample Code

C++
using namespace TLibWin; // Do not forget this

...

tMemSegment sections;

try
{
   sections.Add(0, tMemSection());
   sections.Add(1, tMemSection());
   sections.Add(2, tMemSection());

   printf( "\n tMemSegment contains %ld sections", sections.Count() );

   sections.Clear();

   printf( "\n tMemSegment contains %ld sections", sections.Count() );
}
catch(tMemException e)
{
   printf( "\nException code = %ld / system = %ld\n", e.ecode, e.sys_error );
   exit(0);
}

 See also:

    Add, Section

 

4.2 tMemSegment::Add

 void Add(DWORD _id, tMemSection &_section)

    Adds a new object tMemSection.

Parameters

ParameterMeaning
_id   [in, required]ID that names the tMemSection object.
_section  [in, required]A tMemSection object.

Return

    If call succeeds object is added.

    Otherwise an exception can be raised depend upon result of call:

  • tMemException(tcErrorSectionIDAlreadyExists): if _id already exists.

Sample Code

 

C++
tMemSegment sections;
tMemSection sec;

// Allocating 50 memory blocks
for ( DWORD ii = 0; ii < 50; ii++ )
   sec.AllocAndSet(50, "0123456789", sizeof("0123456789"), tMemPtrID(ii));

// Object is added not the reference!
sections.Add(100, sec);
sec.FreeAll();

printf( "\nTotal memory blocks = %ld", sections.Section(100).Count() );

Remarks

 

    Sample code makes some points clear. Add does not add a reference but a copy of entire tMemSection object. So, the output of sample code is:

    Total memory blocks = 50

See also:

    Section, Remove  

4.3 tMemSegment::Clear

 void Clear(void)

    Destroys all tMemSection objects.

Parameters

    None.

Return

    None.

Sample Code

    See Constructor/Destructor sample code.

See also:

    Add, Remove 

4.4 tMemSegment::Count

DWORD Count(void)

    Retrieves the number of tMemSection objects.

Parameters

    None.

Return

    Total the tMemSection objects.

Sample Code

    See Constructor/Destructor sample code.

See also:

    Add, Remove 

 

4.5 tMemSegment::Pointers

DWORD Pointers(void)

    Retrieves the total memory blocks allocated by all tMemSection objects.

Parameters

    None.

Return

    Total memory blocks allocated by all tMemSection objects..

Sample Code

    See Remove sample code.

See also:

    Add, Remove 

 

4.6 tMemSegment::Remove

void Remove(DWORD _id)

    Destroys a tMemSection object.

Parameters

ParameterMeaning
_id   [in, required]ID that names the tMemSection object.

Return

    If call succeeds tMemSection object is destroyed.

    Otherwise an exception can be raised depend upon result of call:

  • tMemException(tcErrorSectionNotFound): if _id is not valid.

Sample Code

 
C++
try
{
   tMemSegment sections;
   tMemSection sec1;
   tMemSection sec2;

   // sec1 allocates 100 memory blocks
   for ( DWORD ii = 0; ii < 100; ii++ )
      sec1.AllocAndSet(25, "0123456789", sizeof("0123456789"), tMemPtrID(ii));

   // sec2 allocates 100 memory blocks with the same contents of sec1
   sec2 = sec1;

   sections.Add(10, sec1);
   sections.Add(11, sec2);

   sec1.FreeAll();
   sec2.FreeAll();

   DWORD tuser = 0, tsystem = 0;

   tuser = sections.Size(&tsystem);

   printf( "\nTotal Memory Blocks: %ld\nTotal Size User/System: %ld bytes/%ld bytes",
           sections.Pointers(), tuser, tsystem );

   // Removes one of tMemSection objects
   sections.Remove(10);

   tuser = sections.Size(&tsystem);

   printf( "\n\nTotal Memory Blocks: %ld\nTotal Size User/System: %ld bytes/%ld bytes",
           sections.Pointers(), tuser, tsystem );
}
catch(tMemException e)
{
   printf( "\nException code = %ld / system = %ld\n", e.ecode, e.sys_error );
   exit(0);
}

Remarks

    The sample code output is:

    Image 3    

See also:

    Add, Clear 

 

4.7 tMemSegment::Section

tMemSection &Section(DWORD _id)

    Retrieves a reference to a tMemSection object.

Parameters

ParameterMeaning
_id   [in, required]ID that names the tMemSection object.

Return

    If call succeeds tMemSection object reference is returned.

    Otherwise an exception can be raised depend upon result of call:

  • tMemException(tcErrorSectionNotFound): if _id is not valid.

Sample Code

 
C++
try
{
   tMemSegment sections;

   sections.Add(10, tMemSection());
   sections.Add(11, tMemSection());

   for ( DWORD ii = 0; ii < 100; ii++ )
      sections.Section(10).AllocAndSet(25, "0123456789", sizeof("0123456789"),
      tMemPtrID(ii));

   sections.Section(11) = sections.Section(10);

   DWORD tuser = 0, tsystem = 0;

   tuser = sections.Size(&tsystem);

   printf( "\n Total Memory Blocks: %ld\n Total Size User/System: %ld bytes/%ld bytes",
           sections.Pointers(), tuser, tsystem );

   sections.Remove(10);

   tuser = sections.Size(&tsystem);

   printf( "\n Total Memory Blocks: %ld\n Total Size User/System: %ld bytes/%ld bytes",
           sections.Pointers(), tuser, tsystem );
}
catch(tMemException e)
{
   printf( "\nException code = %ld / system = %ld\n", e.ecode, e.sys_error );
   exit(0);
}

Remarks

    The sample output is identical to Remove sample.

See also:

    Add, Remove 

 

4.8 tMemSegment::Size

DWORD Size(DWORD *_sys_size)

    Retrieves total memory allocated by all tMemSection objects.

Parameters

 

ParameterMeaning
_sys_size   [out, optional]Returned the real allocated size of memory.

Return

 

    If call succeeds total size of allocated memory is returned. If _sys_size is not NULL then the real size of total memory that is rounded up to a multiple of MEM_CHUNK is returned too.

    Otherwise 0 is returned.

Sample Code

 

    See Remove sample code.

Remarks

     Size function returns the sum of all memory blocks sizes of all tMemSection objects.

 See also:

     Add, Remove 

5. tMemPtr Structure

    tMemPtr structure is used internally to organize memory block information. You will only have access to it  by using FirstPtr/NextPtr.

 

MemberMeaning
BOOL indexed When TRUE memory block has an ID.
tMemPtrID idID of memory block. Only valid when indexed member is TRUE.
DWORD ptrPointer to memory block.
DWORD user_sizeSize requested by user.
DWORD system_sizeReal size calculated by tMemSection.

6. Conclusion

     I hope these classes are useful to you.  

     Enjoy, hope this helps.

History

  • 15 July, 2009: First version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)