• UWP开发细节记录:WRL::ComPtr 的坑


    WRL::ComPtr 取原始指针的地址有两种方式:

    • operator&()      先释放原指针再取地址
    • GetAddressOf()  直接得到原始指针的地址

    显然,operator& 是为COM风格的API设计的,比如下面这种:

    HRESULT CreateObject(/* [out] */IUnknown** ppObj);

    在这一点上和 ATL::CComPtr 一致,实现上则有不同。上面这种 API 最容易出现的错误是传了一个非空指针的地址给 ppObj ,然后指针被覆盖导致原来指向的对象无法释放。ATL::CComPtr 的解决办法是在 operator& 的实现中加了一个断言,如果指针非空就弹出警告;WRL::ComPtr 的解决办法如上所述,先释放再取地址。

    从使用的角度 WRL::ComPtr 更方便,但从设计角度看实际上违背了运算符重载的基本原则。在不看文档的情况下没人能预期到 operator& 会修改原指针的值,这就是坑

    如下面这样一个 API:

    HRESUTL SetObjects(/* [in] */IUnknown** ppObjs, /* [in] */int count);

    双重指针参数实际代表的是一个指针数组,而非类似 CreateObject 中的指针地址。在数组长度为 1 时,习惯上直接取指针地址设为 ppObjs 参数,然后将 count 设为1 ,如下:

    1 IUnknown* ptr = NULL;           // 正确
    2 // ATL::CComPtr<IUnknown> ptr;  // 警告
    3 // WRL::ComPtr<IUnknown> ptr;   // 悲剧
    4 
    5 CreateObject(&ptr);
    6 SetOjbects(&ptr, 1);        // 注意这里

    注意第六行的代码,无论 ptr 是裸指针还是ATL::CComPtr 包装的智能指针都正确的,不过 CComPtr 会引发断言失败使得我们不得不修改成其他实现方式;WRL::ComPtr 智能指针则编译运行一切正常结果却是悲剧。

    以后使用 WRL::ComPtr 只能小心些了,只在 out 语义的参数中使用 operator& 其他一律用 GetAddressOf ,或者全部用 GetAddressOf 然后在用作 out 语义的参数前写断言。

    设计上的小聪明还是要不得,哪怕是微软。

    MSDN 中关于 ComPtr::operator& 运算符的备注说明 :

    This method differs from ComPtr::GetAddressOf in that this method releases a reference to the interface pointer.Use ComPtr::GetAddressOf when you require the address of the interface pointer but do not want to release that interface.

    https://msdn.microsoft.com/zh-cn/library/vs/alm/br230430.aspx

    2016.03.12 补充:ComPtr 还有一个 ReleaseAndGetAddressOf 方法, out 语义的参数可以用这个方法取指针地址。而 ComPtr::operator& 方法返回的实际上是 ComPtr 对象指针的一个包装类,该包装类在转换为 void** 或者 T** 时实际上也是调用了 ComPtr::ReleaseAndGetAddressOf 方法。

    作者:小时了了
    原创文章,欢迎转载,但请以链接形式注明本文地址.
  • 相关阅读:
    OPC 详解 第一篇 基础概念
    k8s笔记驱逐与重调度,以及deschueduler的一次实验
    Go 记录一次groutine通信与context控制
    k8s随笔descheduler源码简读
    如何清空历史告警记录——WGCLOUD
    WGCLOUD v3.3.6 支持给主机分组了
    WGCLOUD管理端页面访问地址是什么
    介绍一款轻量实用的网络心跳监测工具——WGCLOUD
    什么是WGCLOUD?
    WGCLOUD监控系统的告警阈值和开关在哪儿配置
  • 原文地址:https://www.cnblogs.com/xrunning/p/5246263.html
Copyright © 2020-2023  润新知