65.9K
CodeProject 正在变化。 阅读更多。
Home

tMemSection 类:跟踪数千个指针(动态内存分配)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (11投票s)

2009 年 7 月 21 日

CPOL

15分钟阅读

viewsIcon

28801

downloadIcon

435

演示如何使用几个类对内存块进行分组和组织。

tms_demo

引言

动态内存分配是专业 C++ 应用程序的需求。然而,这种做法有点容易出错,因为开发人员很多时候可能会忘记调用 free、HeapFree 或 delete 来释放先前分配的内存。

在本文中,我将介绍两个类来帮助您管理数百或数千个内存块:tMemSegmenttMemSection

tMemSection 封装了 Windows 操作系统支持的多个堆概念。它提供:

  • 使用 Win32 堆函数进行动态内存分配。
  • 按唯一 ID 分组和排序内存块。
  • 多线程支持:类成员是线程安全的。

tMemSegment 仅仅是 tMemSection 对象的容器。您可以对许多 tMemSection 对象进行分组和排序。

目录

1. Windows 上的堆和 tlw_memory.h 概览

在 Windows 上运行的每个进程都有一个系统提供的默认堆——也称为进程堆。任何进程都从其自己的进程堆动态分配内存。Windows 允许开发人员使用 堆函数创建额外的堆以提高进程性能。每个额外的堆是调用进程地址空间中一个或多个页面的一个区段。

因此,tMemSection 类的每个实例都对应于进程的一个新堆。

tMemSection 的所有功能都在 tlw_memory.h 中。这意味着您只需在 Win32 或 MFC 项目中 #include 它即可开始使用。下表显示了 tlw_memory.h 的内容(类和类型)及其简要描述。

类型 它是什么
tMemExceptionCode tMemSectiontMemSegment 使用的所有可用异常代码的枚举。
tMemException 成员函数引发的异常对象。
tSyncObj 提供同步的简单对象。它由 tMemSection/tMemSegment 的实例使用,以保证线程安全访问。
tMemPtr 表示指针信息的类型。
tMemPtrID 用于创建内存块 ID 的类型。
tMemSection 处理动态内存使用的类。
tMemSegment 实现 tMemSection 对象容器的类。

1.1 使用 tlw_memory.h 时避免 MFC 编译错误

您会注意到 tMemSectiontMemSegment 使用 STL map 和 set 类型来分组和排序指针信息。如果您曾经尝试将 STL 与 MFC 一起使用,您可能会遇到一些难看的编译错误。

好吧,当我尝试在调试模式下编译我的 SampleApp 时,我不得不处理一个恼人的错误:

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

每次我切换到调试配置时,都会发生错误 C2061。花了一些时间才意识到错误的原因是一个 #define

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

DEBUG_NEW 是 MFC 调试工具箱的一部分。它重新定义了 new 运算符,这在使用 STL 时会导致问题。因此,简单的解决方案是:

#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 ...

所以,请记住在 DEBUG_NEW 定义之前包含 tlw_memory.h 以避免问题。明白了吗?

2. SampleApp 的作用是什么?

SampleApp (图 1) 使用了 tMemSectiontMemSegment 类的一些功能。其目的是演示如何使用多个堆(或区段)来提高应用程序性能,或者至少使源代码更清晰。

SampleApp 分两步运行:

  • 第 1 步:读取用户选择路径中的所有文件,并将文件信息保存在两个区段(或堆)中。内存信息如列表 1 所示。
  • 第 2 步:将先前保存在这两个区段中的所有信息传输到列表 2。

查看 Globals.h

using namespace TLibWin;

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

extern tMemSegment vg_memory;

tMemSectiontMemSegment 位于 TLibWin 命名空间中。因此,您应该始终在访问它们之前输入 using namespace TLibWin

这三个定义是用于命名和排序 tMemSegment 容器中的 tMemSection 的 ID。

现在查看 SampleAppDlg.cppCSampleAppDlg::OnInitDialog 函数:

   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

您可以看到正在实例化三个 tMemSection 对象。Add 函数的第一个参数指定用于访问这些 tMemSection 对象的 ID。

您可以在阅读本文的下一部分(描述 tMemSectiontMemSegment 操作)的同时自行探索 SampleApp 源代码的其余部分。

注意:SampleApp 可以扫描整个分区,但如果您没有以管理员权限登录,某些文件夹可能无法读取(例如,System32 文件夹)。在这种情况下,将不会扫描无法访问的文件夹。

3. tMemSection 类成员

tMemSection 负责分配/释放内存块,并将所有指针保存在一个容器中。这些指针可能按 ID 排序,也可能不按 ID 排序。

3.1 构造/析构

tMemSection() 

    tMemSection 构造一个新对象。每个 tMemSection 对象都关联一个堆。

~tMemSection()     

释放所有已分配内存并销毁额外堆。

参数

无。

返回

如果构造成功,则返回 tMemSection 的新实例。

否则,将引发 tMemException(tcErrorCantCreateNewSection) 对象异常。

示例代码

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

备注

    MEM_SECTION_SIZE 定义堆的初始值——默认情况下为 1 兆字节。新堆根据内存分配进行增长。

另请参阅

    AllocAllocAndSet

3.2 tMemSection::Alloc

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

分配 _size 字节的内存。

参数

 

参数 含义
_size [in, required] 要分配的字节数。
_id [in, optional] 一个唯一的 tMemPtrID 类型 ID,用于命名内存块。通过设置 ID,您无需保存返回的内存块指针,并且可以随时通过提供 ID 来检索该指针。tMemSection::tcNoId 表示未传递 ID。

返回

如果调用成功,则返回指向内存块的新指针。

否则,根据调用结果,可能会引发以下两种异常之一:

  • tMemException(tcErrorCantAllocateMemory):如果分配失败。
  • tMemException(tcErrorPointerIDAlreadyExists):如果传递了重复的 ID。

示例代码

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

备注

_size 将向上取整到 MEM_CHUNK 的倍数,以最大程度地减少碎片。

另请参阅

    Free, Ptr, PtrSize

3.3 tMemSection::AllocAndSet

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

分配 _size 字节的内存并将 _data 复制到其中。

参数

 

参数 含义
_size [in, required] 要分配的字节数。
_data [in, required] 要复制的缓冲区。
_data_size [in, required] _data 的大小。
_id [in, optional] 一个唯一的 tMemPtrID 类型 ID,用于命名内存块。通过设置 ID,您无需保存返回的内存块指针,并且可以随时通过提供 ID 来检索该指针。tMemSection::tcNoId 表示未传递 ID。

返回

如果调用成功,则返回一个已用 _data 设置的新指针。

否则,根据调用结果,可能会引发以下三种异常之一:

  • tMemException(tcErrorCantAllocateMemory):如果分配失败。
  • tMemException(tcErrorPointerIDAlreadyExists):如果传递了重复的 ID。
  • tMemException(tcErrorInvalidArgument):如果 _data 为 NULL 或 _data_size 为 0。

示例代码

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

备注

_size 将向上取整到 MEM_CHUNK 的倍数,以最大程度地减少碎片。

如果 _data_size > _size,则内存块大小为 _data_size

另请参阅

    Free, Ptr, PtrSize, Set, SetAt

 

3.4 tMemSection::Count

DWORD Count(void)

检索当前分配的内存块数量。

参数

无。

返回

内存块数量。

示例代码

DWORD total = sec.Count();

另请参阅

    TotalSize

 

3.5 tMemSection::FirstPtr

BOOL FirstPtr(tMemPtr &_ptr)

开始内存块枚举。

参数

 

参数 含义
tMemPtr [out, required] tMemSection::tPointer。包含指针信息的结构体。

返回

如果至少有一个内存块已分配并具有相应的 tMemPtr 信息,则为 TRUE。

否则返回 FALSE。

示例代码

      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) );

备注

        FirstPtrNextPtr 是一种在您没有任何其他信息(既没有指针也没有 ID)时访问指针信息的方法。实际上,您可能永远不会使用它们。您必须将此成员函数与 NextPtr 一起使用。

另请参阅

    NextPtr

3.6 tMemSection::Free

void Free(LPVOID _ptr)

void Free(tMemPtrID _id)

释放之前由 Alloc 和 AllocAndSet 成员函数分配的内存块。

参数

 

参数 含义
_ptr [in, required] AllocAllocAndSet 返回的内存块指针。
_id [in, required] 命名内存块的 ID。

返回

无。

示例代码

      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)

另请参阅

    AllocAllocAndSetFreeAll

 

3.7 tMemSection::FreeAll

void FreeAll(BOOL _bFreeAtOnce = FALSE)

释放所有已分配的内存块。

参数

 

参数 含义
_bFreeAtOnce [in, optional] 当为 TRUE 时,调用 HeapDestroy 而不调用 HeapFree。旧堆被销毁,并在操作期间创建一个新堆。当为 FALSE 时,内存块通过使用 HeapFree 一个接一个地释放。

返回

无。

示例代码

      tMemSection sec1;
      tMemSection sec2;
      
      ...

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

备注

    Destructor 调用 FreeAll(TRUE) 以提高性能。Heap API 允许您调用 HeapDestroy 而不调用 HeapFree 函数。

另请参阅

    AllocAllocAndSetFree

3.8 tMemSection::Get 和 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)

从命名内存块检索数据。

参数

参数 含义
_id [in, required] 命名内存块的 ID。
_at [in, required] 内存块中的字节位置。
_ret_data [out, required] 指向接收内存块数据的缓冲区的指针。
_ret_data_size [in, required] _ret_data 缓冲区的大小。

返回

如果调用成功,_ret_data 被填充,并返回指向由 _id 引用的内存块的指针。

否则,根据调用结果,可能会引发以下三种异常之一:

  • tMemException(tcErrorPointerNotFound):如果 _id 不存在。
  • tMemException(tcErrorInvalidArgument):如果 _ret_data 无效或 _ret_data_size 为 0。
  • tMemException(tcErrorOutOfRange):如果 _ret_data_size_at+_ret_data_size 大于内存块的大小。

示例代码

 

// *** 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;
}

备注

示例代码展示了一个生产者消费者应用程序。在输出中,Count 必须为 0 或 1。

在运行多线程应用程序时,使用 Get/GetAtSet/SetAt 进行同步。内存块必须命名才能使用这些成员函数。

另请参阅

    Set, SetAt, Alloc, AllocAndSet

 

3.9 tMemSection::Grow

LPVOID Grow(LPVOID _ptr, DWORD _bytes)

LPVOID Grow(tMemPtrID _id, DWORD _bytes)

增加内存块的 N _bytes

参数

 

参数 含义
_ptr [in, required] AllocAllocAndSet 返回的内存块指针。
_id [in, required] 命名内存块的 ID。
_bytes [in, required] 增加内存块的字节数。

返回

如果调用成功,则返回指向内存块的指针。

否则,根据调用结果,可能会引发以下两种异常之一:

  • tMemException(tcErrorPointerNotFound):如果 _id 或 _ptr 不存在。
  • tMemException(tcErrorCantAllocateMemory):如果分配失败。

示例代码

 

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

备注

增加大小后,原始内存块内容保持不变。

新内存块大小也会向上取整到 MEM_CHUNK,以最大限度地减少碎片。

另请参阅

    AllocAllocAndSet

3.10 tMemSection::NextPtr

 BOOL NextPtr(tMemPtr &_ptr)

继续指针枚举。

参数

 

参数 含义
tMemPtr [out, required] tMemSection::tPointer。包含指针信息的结构体。

返回

如果至少有两个内存块并且有相应的 tMemPtr 信息,则返回 TRUE。

否则返回 FALSE。

示例代码

      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) );

备注

FirstPtr 和 NextPtr 是一种在您没有任何其他信息(既没有指针也没有 ID)时访问指针信息的方法。实际上,您可能永远不会使用它们。您必须将此成员函数与 FirstPtr 一起使用。

另请参阅

    FirstPtr

 

3.11 tMemSection::Ptr

 LPVOID Ptr(tMemPtrID _id)

通过 ID 检索指向内存块的指针。

参数

 

参数 含义
_id [in, required] 命名内存块的 ID。

返回

如果 ID 存在,则返回内存块的指针。

否则返回 NULL。

示例代码

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

备注

命名内存块为您提供了更大的灵活性,因为您不必担心保存指针。

另请参阅

    AllocAllocAndSet

 

3.12 tMemSection::PtrSize

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

检索内存块的用户定义大小和系统定义大小(四舍五入到 MEM_CHUNK 大小)。

参数

 

参数 含义
_ptr [in, required] AllocAllocAndSet 返回的内存块指针。
__sys_size [out, optional] 返回实际分配的内存块大小(四舍五入到 MEM_CHUNK 大小)。

返回

 

如果调用成功,则返回内存块的大小。如果 _sys_size 不为 NULL,则也返回四舍五入到 MEM_CHUNK 倍数的实际块大小。

否则返回 0。

示例代码

 
   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);

备注

    tMemSection 分配用户请求的字节大小。然而,为了最小化碎片,大小会向上取整到 MEM_CHUNK 的倍数。

另请参阅

    TotalSize

3.13 tMemSection::Set 和 SetAt

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

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

将数据设置到已命名的内存块。

参数

参数 含义
_id [in, required] 命名内存块的 ID。
_at [in, required] 内存块中的字节位置。
_data [out, required] 指向用于设置内存块的缓冲区的指针。
_data_size [in, required] _data 缓冲区的大小。

返回

如果调用成功,则返回指向由 _id 引用的内存块的指针。

否则,根据调用结果,可能会引发以下三种异常之一:

  • tMemException(tcErrorPointerNotFound):如果 _id 不存在。
  • tMemException(tcErrorInvalidArgument):如果 _data 无效或 _data_size 为 0。
  • tMemException(tcErrorOutOfRange):如果 _data_size_at+_data_size 大于内存块的大小。

示例代码

 

    请参阅 Get/GetAt 示例代码。

另请参阅

    Get, GetAt

 

3.14 tMemSection::TotalSize

DWORD TotalSize(DWORD *_sys_size = NULL)

检索由 tMemSection 对象分配的总内存。

参数

 

参数 含义
_sys_size [out, optional] 返回实际分配的内存大小(四舍五入到 MEM_CHUNK 大小)。

返回

 

如果调用成功,则返回分配内存的总大小。如果 _sys_size 不为 NULL,则也返回四舍五入到 MEM_CHUNK 倍数的总内存实际大小。

否则返回 0。

示例代码

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

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

   sz1 = sec.TotalSize(&sz2);

备注

     TotalSize 返回所有内存块大小的总和。

另请参阅

    PtrSize

3.15 tMemSection::operator=

    operator= 将所有内存块复制到另一个 tMemSection 对象。

示例代码

 
   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() );

备注

 

operator= 的结果是一个目标对象,它包含相同数量的内存块,在不同的堆中具有相同的内容。示例代码输出如下:

图 2 - 示例代码输出

 

4. tMemSegment 类成员

    tMemSegment 类提供了一个包含 1 到 N 个 tMemSection 对象的容器。tMemSection 对象按 DWORD 值排序。

 

4.1 构造/析构

tMemSegment() 

    tMemSegment 构造一个新对象。

~tMemSegment()     

销毁所有 tMemSection 对象并释放所有内存。

参数

无。

返回

tMemSegment 的新实例。

示例代码

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

另请参阅

    Add, Section

 

4.2 tMemSegment::Add

 void Add(DWORD _id, tMemSection &_section)

添加一个新的 tMemSection 对象。

参数

参数 含义
_id [in, required] 命名 tMemSection 对象的 ID。
_section [in, required] 一个 tMemSection 对象。

返回

如果调用成功,则添加对象。

否则,根据调用结果,可能会引发异常:

  • tMemException(tcErrorSectionIDAlreadyExists):如果 _id 已存在。

示例代码

 

      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() );

备注

 

示例代码阐明了一些要点。Add 不添加引用,而是添加整个 tMemSection 对象的副本。因此,示例代码的输出是:

内存块总数 = 50

另请参阅

    Section, Remove

4.3 tMemSegment::Clear

void Clear(void)

销毁所有 tMemSection 对象。

参数

无。

返回

无。

示例代码

    请参阅构造函数/析构函数示例代码。

另请参阅

    Add, Remove

4.4 tMemSegment::Count

DWORD Count(void)

检索 tMemSection 对象的数量。

参数

无。

返回

tMemSection 对象的总数。

示例代码

    请参阅构造函数/析构函数示例代码。

另请参阅

    Add, Remove

 

4.5 tMemSegment::Pointers

DWORD Pointers(void)

检索由所有 tMemSection 对象分配的总内存块。

参数

无。

返回

所有 tMemSection 对象分配的总内存块。

示例代码

    请参阅 Remove 示例代码。

另请参阅

    Add, Remove

 

4.6 tMemSegment::Remove

void Remove(DWORD _id)

销毁一个 tMemSection 对象。

参数

参数 含义
_id [in, required] 命名 tMemSection 对象的 ID。

返回

如果调用成功,tMemSection 对象将被销毁。

否则,根据调用结果,可能会引发异常:

  • tMemException(tcErrorSectionNotFound):如果 _id 无效。

示例代码

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

备注

示例代码输出如下:

        

另请参阅

    Add, Clear

 

4.7 tMemSegment::Section

tMemSection &Section(DWORD _id)

检索对 tMemSection 对象的引用。

参数

参数 含义
_id [in, required] 命名 tMemSection 对象的 ID。

返回

如果调用成功,则返回 tMemSection 对象的引用。

否则,根据调用结果,可能会引发异常:

  • tMemException(tcErrorSectionNotFound):如果 _id 无效。

示例代码

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

备注

示例输出与 Remove 示例相同。

另请参阅

    Add, Remove

 

4.8 tMemSegment::Size

DWORD Size(DWORD *_sys_size)

检索由所有 tMemSection 对象分配的总内存。

参数

 

参数 含义
_sys_size [out, optional] 返回实际分配的内存大小。

返回

 

如果调用成功,则返回分配内存的总大小。如果 _sys_size 不为 NULL,则也返回四舍五入到 MEM_CHUNK 倍数的总内存实际大小。

否则返回 0。

示例代码

 

    请参阅 Remove 示例代码。

备注

Size 函数返回所有 tMemSection 对象的所有内存块大小的总和。

另请参阅

     Add, Remove

5. tMemPtr 结构体

    tMemPtr 结构体内部用于组织内存块信息。您只能通过使用 FirstPtr/NextPtr 访问它。

 

成员 含义
BOOL indexed 当为 TRUE 时,内存块具有 ID。
tMemPtrID id 内存块的 ID。仅当 indexed 成员为 TRUE 时有效。
DWORD ptr 指向内存块的指针。
DWORD user_size 用户请求的大小。
DWORD system_size tMemSection 计算的实际大小。

6. 结论

我希望这些类对您有用。

享受,希望这有所帮助。

历史

  • 2009 年 7 月 15 日:第一个版本
© . All rights reserved.