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 ,如下:
IUnknown* ptr = NULL; // 正确
// ATL::CComPtr<IUnknown> ptr; // 警告
// WRL::ComPtr<IUnknown> ptr; // 悲剧 CreateObject(&ptr);
SetOjbects(&ptr, ); // 注意这里
注意第六行的代码,无论 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 方法。
UWP开发细节记录:WRL::ComPtr 的坑的更多相关文章
- UWP开发细节记录:DirectX::XMMATRIX 的坑
这两天写的代码概率性的崩溃在 XMMatrixMultiply() 函数,XMMatrixMultiply() 本身是 inline 函数可以看到崩溃处的代码: vX = _mm_mul_ps(vX, ...
- UWP开发细节记录:加载图像文件到D2D位图和D3D纹理
在UWP中加载文件一般先创建 StorageFile 对象,然后调用StorageFile.OpenReadAsync 方法得到一个IRandomAccessStream 接口用来读取数据: Stor ...
- UWP开发细节记录:IStream 和 IRandomAccessStream^ 以及 IMFByteStream 互转
IStream 和 IRandomAccessStream^ 互转 IRandomAccessStream^ --> IStream: CreateStreamOverRandomAccess ...
- UWP开发细节记录:判断文件类型
StorageFile.ContentType 属性,是 string 类型,用来表示文件内容的 MIME 类型.例如,音乐文件可能有 "audio/mpeg" MIME 类型.( ...
- 记UWP开发——多线程操作/并发操作中的坑
一切都要从新版风车动漫UWP的图片缓存功能说起. 起因便是风车动漫官网的番剧更新都很慢,所以图片更新也非常慢.在开发新版的过程中,我很简单就想到了图片多次重复下载导致的资源浪费问题. 所以我给app加 ...
- PC客户端开发细节记录:保存GUID到VARIANT
有两个 API 可以实现保存 GUID 到 VARIANT InitVariantFromGUIDAsBuffer 以字节数组形式保存,保存类型为 VT_ARRAY | VT_UI1,相当于字节拷贝, ...
- java后台开发细节记录
1. ResultMap是程序员控制SQL查询结果和实体类的映射关系,而不是sql语句中字段的重命名,所以在sql语句中还是要按照原来字段的格式进行书写.
- 讲讲我在Windows10(uwp)开发中遇到的一些坑.
7月29日发布的Windows10正式版,当天安装好以后,在网络不太好的情况下,经过多次尝试终于装上了Visual Studio 2015和Windows 10 10240的SDK.这两周一直在开发U ...
- 领域驱动和MVVM应用于UWP开发的一些思考
领域驱动和MVVM应用于UWP开发的一些思考 0x00 起因 有段时间没写博客了,其实最近本来是根据梳理的MSDN上的资料(UWP开发目录整理)有条不紊的进行UWP学习的.学习中有了心得体会或遇到了问 ...
随机推荐
- p132代码解析
1. long before = System.currentTimeMillis(); long after = System.currentTimeMillis(); //该两句代码规定了一个do ...
- Jmeter报错之jmeter.gui.action.ActionRouter: Error processing gui.action.Start@1b7c473a java.lang.ArrayIndexOutOfBoundsException
一个使用了很久的Jmeter脚本,运行时Jmeter的UI界面上点击绿色按钮后,完全无反应,只有log报错,如下: 2017/06/28 14:29:23 ERROR - jmeter.gui.act ...
- 编译开源C或者C++项目最好像执行如下命令,否则可能会有这种奇葩问题
find ./ -type f | xargs sed -i 's/\r$//' find ./ -name "*.sh" | xargs chmod +x find ./ -ty ...
- BIO与NIO、AIO的区别(这个容易理解)
转自:http://blog.csdn.net/skiof007/article/details/52873421 BIO与NIO.AIO的区别(这个容易理解) IO的方式通常分为几种,同步阻塞的BI ...
- 【SpringBoot系列5】SpringBoot整合RabbitMQ
前言: 因为项目需要用到RabbitMQ,前几天就看了看RabbitMQ的知识,记录下SpringBoot整合RabbitMQ的过程. 给出两个网址: RabbitMQ官方教程:http://www. ...
- flex弹性布局学习总结
本文首次发布在我的个人博客:Claiyre的个人博客 https://claiyre.github.io/ 博客园地址:http://www.cnblogs.com/nuannuan7362/如需转载 ...
- [转]Vue.js 入门教程
本文转自:http://www.runoob.com/w3cnote/vue-js-quickstart.html 什么是 Vue.js? Vue.js 是用于构建交互式的 Web 界面的库. Vu ...
- MVC添加数据并存入数据库
你可以下载演示的数据库,在这篇<MVC显示详细记录Without Entity Framework>http://www.cnblogs.com/insus/p/3366608.html结 ...
- winform窗体 控件【MDI 窗体容器】
MDI :窗体容器 -- 在窗体中放置窗体 属性 IsMdiContainer : 是否是窗体 -- 只有 Form 有此属性 Form2 f2 = new Form2(); ...
- 转载-增删改查sql语句语法
一.增:有2种方法 1.使用insert插入单行数据: 语法:insert [into] <表名> [列名] values <列值> 例:insert into Strdent ...