COM 接口指针很危险, 因为使用过程中需要每一个使用者都要严格并且正确的 AddRef 和 Release, 一旦出现问题, 就会造成对象不能被正常释放, 或者对象被重复删除, 造成程序崩溃. 所以使用 COM 接口, 必须小心翼翼才行.
但是, 即使所有的代码中, 都正确的 AddRef 和 Release, 也不一定能保证万无一失, 例如:
- void SomeApp( IHello * pHello )
- {
- IHello* pCopy = pHello;
- pCopy->AddRef();
- OtherApp();
- pCopy->Hello();
- pCopy->Release();
- }
看起来好像无懈可击, 但是假设 OtherApp 中抛出了异常, 那么 pCopy->Release 不就被跳过去了吗?
幸好, 所有的问题都从简单到复杂, 再从复杂到简单的, 因为我们有 CComPtr!
2.** 智能指针 **
CComPtr 被称为智能指针, 是 ATL 提供的一个模版类, 能够从语法上自动完成 AddRef 和 Release.(源代码在 atlbase.h 中)
CComPtr 的用法很简单, 以 IHello * 为例, 将程序中所有接口指针类型(除了参数), 都使用 CComPtr 代替即可. 即程序中除了参数之外, 再也不要使用 IHello*, 全部以 CComPtr 代替.
CComPtr 的用法和普通 COM 指针几乎一样, 另外使用中有以下几点需要注意.
1. CComPtr 已经保证了 AddRef 和 Release 的正确调用, 所以不需要, 也不能够再调用 AddRef 和 Release.
2. 如果要释放一个智能指针, 直接给它赋 NULL 值即可.(这一点要牢记曾因为没有设置为 null 而出错)
3. CComPtr 本身析构的时候会释放 COM 指针.
4. 当对 CComPtr 使用 & 运算符 (取指针地址) 的时候, 要确保 CComPtr 为 NUL.(因为通过 CComPtr 的地址对 CComPtr 赋值时, 不会自动调用 AddRef, 若不为 NULL, 则前面的指针不能释放, CComPtr 会使用 assert 报警)
以刚才的程序为例:
- void SomeApp( IHello * pHello )
- {
- CComPtr pCopy = pHello;
- OtherApp();
- pCopy->Hello();
- }
由于 pCopy 是一个局部的对象, 所以即使 OtherApp()抛出异常, pCopy 也会被析构, 指针能够被释放.
如果不想在程序临近发布前, 还因为 COM 指针的引用计数造成崩溃的话, 就牢记这一点吧: 程序中除了参数之外, 不要直接使用 COM 指针类型, 一定要全部以 CComPtr 代替.
3. ** 示例 **```
- void OnDrawImage(CDC *pDC, unsigned char* pbyteImage, int size,CRect rect)
- {
- CImage image;
- CComPtr stream;
- stream = NULL;
- HGLOBAL hMem = ::GlobalAlloc(GHND, size); // 从堆中分配一定数目的字节数 GHND 为分配方式 (可移动且初始为 0) 返回一个新分配的内存对象的句柄.
- LPVOID pBuff = ::GlobalLock(hMem);// 锁定内存中指定的内存块, 并返回一个地址值, 令其指向内存块的起始处. 除非用 GlobalUnlock 函数将内存块解锁, 否则地址会一直保持有效.
- memcpy(pBuff, pbyteImage, size);
- ::GlobalUnlock(hMem);// 解锁内存块
- CreateStreamOnHGlobal(hMem, TRUE, &stream);// 从指定内存创建流对象 TRUE: 自动释放内存
- image.Load(stream);
- // Drawing
- SetStretchBltMode(pDC->GetSafeHdc() , COLORONCOLOR);
- image.StretchBlt(pDC->GetSafeHdc(), rect.left,rect.top,rect.Width(),rect.Height(),0,0,image.GetWidth(), image.GetHeight(),SRCCOPY);
- image.Destroy();
- ::GlobalFree(hMem);// 释放指定的全局内存块
- }
- ```
来源: https://www.2cto.com/kf/201810/782920.html