windows GDI调色板是否存在内存泄露 之鉴 free函数用法

来源:互联网 发布:论李维 知乎 编辑:程序博客网 时间:2024/05/19 02:25

根据《Opengl超级宝典》第三版的范例程序,可知这么一段代码:

HPALETTE GetOpenGLPalette(HDC hDC)
{
 HPALETTE hRetPal = NULL;
 PIXELFORMATDESCRIPTOR pfd;
 LOGPALETTE *pPal;
 int nPixelFormat;
 int nColors;
 int i;
 BYTE RedRange,GreenRange,BlueRange;

 nPixelFormat = GetPixelFormat(hDC);
 DescribePixelFormat(hDC, nPixelFormat, sizeof(PIXELFORMATDESCRIPTOR),&pfd);

 if(!(pfd.dwFlags & PFD_NEED_PALETTE))
  return NULL;

 nColors = 1 << pfd.cColorBits;

 pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE)+nColors*sizeof(PALETTEENTRY));

 pPal->palVersion = 0x300;
 pPal->palNumEntries = nColors;

 RedRange = (1<<pfd.cRedBits) - 1;
 GreenRange = (1<<pfd.cGreenBits) - 1;
 BlueRange = (1<<pfd.cBlueBits) - 1;

 for(i=0; i < nColors;i++)
 {
  pPal->palPalEntry[i].peRed = (i >> pfd.cRedShift) & RedRange;
  pPal->palPalEntry[i].peRed = (unsigned char)(
   (double)pPal->palPalEntry[i].peRed * 255.0 / RedRange);

  pPal->palPalEntry[i].peGreen = (i >> pfd.cGreenShift) & GreenRange;
  pPal->palPalEntry[i].peGreen = (unsigned char)(
   (double)pPal->palPalEntry[i].peGreen * 255.0 / GreenRange);

  pPal->palPalEntry[i].peBlue = (i >> pfd.cBlueShift) & BlueRange;
  pPal->palPalEntry[i].peBlue = (unsigned char)(
   (double)pPal->palPalEntry[i].peBlue * 255.0 / BlueRange);

  pPal->palPalEntry[i].peFlags = (unsigned char)NULL;
 }

 hRetPal = CreatePalette(pPal);

 SelectPalette(hDC,hRetPal,FALSE);
 RealizePalette(hDC);

 free(pPal);

 return hRetPal;

其中,

pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE)+nColors*sizeof(PALETTEENTRY));

这里分配了nColors(假设为256色系统)个PALETTEENTRY结构大小的空间加上一个LOGPALETTE大小的空间,其结构如下:


typedef struct tagLOGPALETTE {
    WORD        palVersion;
    WORD        palNumEntries;
    PALETTEENTRY        palPalEntry[1];
} LOGPALETTE, *PLOGPALETTE, NEAR *NPLOGPALETTE, FAR *LPLOGPALETTE;


typedef struct tagPALETTEENTRY {
    BYTE        peRed;
    BYTE        peGreen;
    BYTE        peBlue;
    BYTE        peFlags;
} PALETTEENTRY, *PPALETTEENTRY, FAR *LPPALETTEENTRY;

可知LOGPALETTE结构中存在一个PALETTEENTRY大小的结构而非指针,那么就是说在释放了动态分配的pPal 以后是否还能够使palPalEntry[0]保存下来,我的答案是“不可能”(这里是我理解free只释了放单个LOGPALETTE结构大小空间的错误所致,请大家注意)。

所以这里将代码

 for(i=0; i < nColors;i++)

改为:

 for(i=1; i <= nColors;i++)

但是另外一个问题出现了,动态分配的空间是否被CreatePalette函数所控制,还是这个函数只是复制了调色板中的内容,我猜测如果不是复制(而是直接传递指针),肯定会出现内存泄露,所以答案应该是复制了这段调色板内存。

所以这个for循环不需要修改。还是

 for(i=0; i < nColors;i++)

然而在释放阶段,应该对所有已经分配的内存,即为pPal所分配的所有内存,而不止LOGPALETTE结构,所以,可以肯定的是在malloc时系统内部已经进行的已分配内存快的纪录,在free的时候就根据这些纪录来释放空间。

MSDN上有这么一段话:

The number of freed bytes is equivalent to the number of bytes requested when the block was allocated (or reallocated, in the case of realloc).

就是这么解释的。

所以创建调色板是对内容进行复制。

以上内容属于个人愚见,还请大家多多指点改正。