第 24 集:作者:卢卡斯·安福罗维奇,华盛顿州贝尔维尤(2021 年 8 月)
上一集
您能在以下代码中找到该 bug 吗?你能看到吗 错误 代码审核中 只查看了调用点?
Token CreateToken(int command_data, int buffer_id);
...
auto token = CreateToken(GetCommandBufferId(), GetCommandData());
相同的类型有时可能表示来自不兼容网域的值。
这通常发生在非特定数据类型(如整数或字符串)中。
上面的示例说明了这可能会导致 bug 的原因。
幸运的是,Chromium 的 //base
可让您轻松引入显式的不同类型:
#include "base/types/strong_alias.h"
// The first template argument of StrongAlias is a "tag" type.
// The "tag" type is used to distinguish between different
// StrongAlias types.
using CommandData = base::StrongAlias<class CommandDataTag, int>;
using CommandBufferId = base::StrongAlias<class CommandBufferIdTag, int>;
Token CreateToken(CommandData command_data, CommandBufferId buffer_id);
单独的类型可提高可读性。
此外,StrongAlias
会在编译时捕获类型混淆:
test.cc:456:16: error: no matching function for call to 'CreateToken'
auto token = CreateToken(GetCommandBufferId(), GetCommandData());
^~~~~~~~~~~
test.cc:123:7: note: candidate function not viable: no known conversion from
'StrongAlias<class CommandBufferIdTag, [...]>' to
'StrongAlias<class CommandDataTag, [...]>' for 1st argument
Token CreateToken(CommandData command_data, CommandBufferId buffer_id);
^
编译器发现类型不兼容,
因为它们具有不同的“代码”类型。
StrongAlias
接受任何类型作为“标记”类型。
本例显示,“tag”因此在任何位置也不需要类型定义,
可以就地向前声明不存在的类。
将来,不再使用非特定类型(例如 bool、int、string), 请考虑以下替代方案:
- 使用
base::IdType32<TagType>
,而不是int32_t
作为标识符。 - 使用
base::TokenType<TagType>
而不是非特定的base::UnguessableToken
。 - 使用枚举类而不是布尔值
(例如,
kForReload
、kNotForReload
,而不是true
、false
)。 - 将其他非特定类型替换为
base::StrongAlias<TagType, SomeWrappedType>
。