西欧|说说有点意思的STRRET结构体


西欧|说说有点意思的STRRET结构体
如果你曾经折腾过外壳命名空间(shell namespace) , 则我想你一定碰到过古怪的STRRET结构体 。
这个结构体是
IShellFolder::GetDisplayNameOf用来返回一些列外壳项目名称的 。
如果你阅读文档就可以知道 , 一个STRRET结构有时候是一个ANSI字符串的缓冲区 , 有时候它又是一个指向UNICODE字符串的指针 , 有时候(这个时候是最奇怪的情况)它会是一个指向一个pidl的偏移量 。
这都什么乱七八糟的?下面我们来具体看看 。
STRRET结构是从Windows 95年代引入的 。 这个年代的计算机系统的性能还是比较慢的 , 内存也不是很大 。 (要知道 , Windows 95的最小硬件需求是4MB的内存和一块25MHz的386DX处理器) 。 在这样的系统上 , 通过在栈(Stack)上分配内存(一条简单的sub指令) , 远比在堆(Heap)上分配内存(这可能需要数千条机器指令)要快得多 , 所以STRRET结构就被设计出来 , 用来应对在一些无需堆内存分配的场景需求 。
STRRET_OFFSET标志进一步将这种性能优化推向极端 。 通常 , 你将名称保留在pidl中 , 并将其复制到 STRRET结构中需要花费200个时钟周期 。 为了避免这种浪费的内存复制 , STRRET_OFFSET允许你只返回一个偏移量到pidl中 , 然后调用者可以直接从中复制出来 。
也就是说 , 通过这种技法 , 我们省掉了一个字符串拷贝操作 。
当然 , 随着时间的推移 , 计算机变得更快 , 内存变得更大 , 这些微优化已经变成了烦恼 。 在字符串复制操作上节省200个时钟周期几乎没什么意义 。 在1GHz处理器上 , 单个软页面错误(soft page fault)就会花费超过一百万个周期 , 而一个硬页面错误会让你损失数千万个时钟周期 。
在这段时间里 , 你都可以复制大量的字符串了 。
更重要的是 , Windows 95中常见的场景已经不那么常见了 , 因此原本为优化量身定制的场景几乎不再出现 。这是一种已经失去效用的优化 。
幸运的是 , 你不必再考虑STRRET结构 。 有几个辅助函数可以将STRRET结构转换为更易于操作的东西 。 所以 , 不需要再在这个结构体上花功夫了 。
总结STRRET结构的怪异之处现在已被简单易用的API封装起来了 , 开发者也舒坦了 。
我也觉得真是谢天谢地了 。
最后Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一 , 里面有很多关于Windows的小知识 , 对于广大Windows平台开发者来说 , 确实十分有帮助 。
本文来自:《The kooky STRRET structure》
【西欧|说说有点意思的STRRET结构体】