如何追踪编译器错误根源?以VS2017的C2070错误为例
如何追踪指向标准库头文件的编译器错误根源
这个问题我之前在VS里踩过好几次坑!当编译器错误指向type_traits这类标准库头文件时,确实完全摸不到头绪——毕竟标准库代码肯定是对的,问题百分百出在我们自己的代码里。针对你遇到的C2070 'unsigned char []': illegal sizeof operand错误,分享几个高效定位的方法:
1. 仔细查看完整的编译输出日志
VS的错误列表窗口默认只显示最顶部的错误,但往下翻你会发现一堆辅助信息(note),这些信息会回溯到你自己代码中触发错误的文件和行号。比如你这个错误,大概率是你在某个地方把数组类型直接传给了依赖sizeof操作的模板(比如std::is_same、std::enable_if这类type_traits模板),编译器在实例化模板时才爆了错,而错误栈的最上层就是标准库头文件。
2. 生成并分析预处理器输出
预处理器会把所有头文件展开,把宏替换完成,能帮你看到标准库模板是被你哪段代码触发实例化的:
- 右键你的项目 → 属性 → C/C++ → 预处理器 → 「生成预处理文件」选择「带行号的预处理文件(/P)」
- 重新编译,项目目录下会生成一个
.i后缀的巨型文件 - 在这个文件里搜索
type_traits的1227行,然后往上翻,找到最近的你自己代码的文件名和行号——那就是问题的根源。
3. 逐步简化/注释代码,最小化复现案例
如果项目比较大,直接找日志费劲,可以试试:
- 先注释掉最近新增的代码,重新编译,看错误是否消失,逐步缩小范围
- 把可疑的代码片段(比如你用到模板的地方)单独拎出来,写一个只包含必要代码的小项目,快速定位哪一行传了非法的数组类型进去。比如你这个错误,大概率是写了类似
std::some_trait<unsigned char[]>这样的代码,或者在模板里对数组类型做了sizeof(T)操作。
4. 检查模板参数的合法性
C2070错误明确说unsigned char []不能作为sizeof的操作数,那你可以重点排查:
- 有没有把数组类型(不是指针)直接作为模板参数传给
type_traits里的模板? - 有没有在自定义模板中,对模板参数
T执行sizeof(T),但调用时传入了数组类型? - 有没有用数组类型初始化某个依赖
sizeof的模板类/函数?
我自己遇到这个错误时,就是不小心把unsigned char arr[]的类型直接传给了std::enable_if的模板参数,导致编译器在实例化type_traits里的代码时触发了检查。
内容的提问来源于stack exchange,提问作者Kazz
相关产品推荐
相关产品推荐

