总结排错vs编译错误错误列表输出窗口

排错排到编译

缘起

最近,项目里出现了一个奇怪的编译错误。乍看错误提示,真有丈二的和尚,摸不着头脑的感觉。解决之后,又是这么的合情合理。具体是什么样的问题呢?一起来看看吧。

**说明:**实际项目中的错误隐藏的更深,完全没有相关的错误提示。因为不方便用项目代码演示,准备了一个简单的例子,大家可以新建一个控制台工程,并把下面的代码粘贴到对应的文件里。

示例代码简介

示例代码比较简单,共有五个关键文件,加起来不到 40 行代码。大家可以先观察一下代码,思考编译是否会遇到问题。

// NameCollisionDemo.cpp
#include "ModifyInfoTest.h"
int wmain(int argc, wchar_t* argv[])
{Test();return 0;
}// ModifyInfo.h
#pragma once
class CModifyInfo
{
public:enum class eSource { None = 0, BayWindow, Beam };CModifyInfo(eSource source_) : source(source_) {}eSource source;
};// ModifyInfoTest.h
#pragma once
#include "ModifyInfo.h"
#include "UiMacros.h"static void Test()
{CModifyInfo info1(CModifyInfo::eSource::BayWindow);CModifyInfo info2(CModifyInfo::eSource::Beam);
}// UiMacros.h
#pragma once
#include "BayWindowUiMacros.h"// BayWindowUiMacros.h
#pragma once
#define BayWindow "Ui.BayWindow"

初识错误

vs 打开工程后,编译,报错如下:

c2589

大家能从图中得到什么信息呢?

  • 第一行提示 error C2059: syntax error : '::'。语法错误?
  • 第二行提示 error C2589: 'string' : illegal token on right side of '::'::右侧有非法符号?
  • 第三行提示 IntelliSense: expected an identifier。期待一个标识符?

**注意:**第三行是 IntelliSense 提示的,不是真正意义上的错误。IntelliSense 提示的错误对是否能成功编译没有影响。注意看图标,不是 大红叉。第三行给出了出错文件(ModifyInfoTest.h)及行号( 6 ),列号 45。书中暗表,这个提示是最接近出错地点的。

关键的悬浮提示

对照代码仔细检查,没问题啊。BayWindow 确实在 SourceType 中定义了,大小写也没问题。使用 Visual AssistX 的快捷键 alt + g 能正常跳转到定义。这是什么情况?如果我们把鼠标放到 BayWindow 上,有可能会看到下图中的提示:

鼠标悬浮提示

Oops,怎么 BayWindow 变成了一个宏?应该是在编译到这条语句前,遇到了一个名字为 BayWindow 的宏。我们接下来的任务是找到这个宏是在哪里定义的,又为什么会出现在这条语句前。

说明: 在实际项目里通过什么方法看都是正常的。alt + g 和 F12 都能正常跳转到定义,鼠标悬停提示也正常。应该是实际的工程太复杂了,智能感知不好使了!

深入调查

solution 范围搜索关键字 BayWindow。可以勾选 Match whole word(全字匹配)和 Match case (大小写匹配) 排除无关的信息。

搜索整个 solution

纳尼?没有这个宏。大写的尴尬(不要问我怎么写)!原来,我们指定搜索范围为 Entire Solution 的时候,vs 只会搜索已经添加到工程的文件。我们需要指定搜索范围为 Entire Solution ( Including External Items )。这样就可以搜到没加到工程里,但是被 include 的头文件了。搜索结果如下图:

搜索 solution 及包含文件

好了,至此我们已经知道 BayWindow 宏定义在 BayWindowUiMacros.h 中了。我们的下一个目标是:找出为什么在编译出错语句前,BayWindow 宏就被定义了。

应该是在出问题的代码前面的某个位置包含了 BayWindowUiMacros.h。我们需要找到这个关键的 #include BayWindowUiMacros.h 语句。

我们可以搜索 BayWindowUiMacros.h,发现只有 UiMacros.h 包含了 BayWindowUiMacros.h。继续搜索 UiMacros.h,我们发现在 ModifyInfoTest.h 的第 3 行包含了 UiMacros.h

找到真相

至此,我们查清了来龙去脉——在 ModifyInfoTest.h 的第 3 行包含了 UiMacros.h,从而间接包含了 BayWindowUiMacros.h,里面定义了名为 BayWindow 的宏。第 6 行的 BayWindow 在预处理阶段被当成宏处理了,所以第 6 行就变成了 WallModifyInfoEx info1(WallModifyInfoEx::SourceType::"Ui.BayWindow")

到底是不是这样的呢?有没有办法验证我们的猜测呢?

说明: 在实际工程中,头文件的包含关系极有可能比这个简单的示例工程复杂的多。手动排查绝对是体力活!我在解决项目里的编译问题的时候,是通过下面的方法排查的。在准备示例工程的时候,通过悬浮提示发现了居然直接提示有问题的地方是一个宏,大大降低了排查难度。有时候,智能感知还是挺有用的。

杀手锏

解决这种问题有一个可以称得上杀手锏的设置 —— Preprocess to a File。这个设置可以把预处理后的文件以编译单元(.cpp, .c 等)为单位输出到 Intermediate Directory (中间目录)。可以在工程设置里修改中间目录的值。

Intermediate Directory 设置

在工程上,右键 -> 属性 打开工程设置。然后设置 Configuration Properties -> C/C++ -> Preprocessor 中的 Preprocess to a FileYes(/P) 就可以把预处理的结果输出到中间目录了。

preprocess to file 设置

上图中右侧黄色高亮的两个选项会影响生成的中间文件的内容,Preprocess Suppress Line NumbersYes(/P) 表示输出的中间文件不包含行号信息,Keep CommentsTrue 表示保留注释,否则不保留。

设置好后,重新编译。就可以生成 .i 文件了。让我们一起查看下生成的中间文件(我生成的时候,输出了行号信息):

查看中间文件

我们发现,有问题的那一行居然变成了 WallModifyInfoEx info1(WallModifyInfoEx::SourceType::"Ui.BayWindow")。证实了我们的猜想。

说明:

  1. 我们怎么知道应该看哪个中间文件呢?真实的项目里,会有 N 多个源文件,我们不可能每个文件都检查一遍。我们可以根据上一篇文章里介绍的 输出窗口Build Order 定位到错误出现在哪个源文件中。示例工程比较简单,就省略了这一步。
  2. 在真实项目里,生成的中间文件会很大。基本不可能用肉眼看,需要靠搜索关键字定位。我们可以把 Keep Comments 设置为 True,然后在出问题的哪一行的后面写一个带特殊标记的注释,搜索特殊标记就可以了。

总结

  • 要充分利用 IDE 给出的提示,Intellisense 还是很有用的,虽然在大工程里经常性的失效。

  • 定义宏的时候,尽量全大写,这样与其它名字冲突的机率会小很多。

  • 源文件必须添加到工程文件中,但是头文件不是必须添加到工程文件里的。

  • 搜索范围指定为 Entire Solution ( Including External Items ),可以在没添加到工程中的头文件中搜索。

  • Preprocess to a File 你记住了吗?

排错实战 —— 解决 c++ 工程编译错: error C2059 'string' illegal token on right side of xxx相关推荐

  1. 解决执行Mysql报错: ERROR: The server quit without updating PID file (/data/xxx.pid)

    昨天在Linux中安装mysql-8.0.28时遇到了这个报错: ERROR! The server quit without updating PID file (/data/xxx.pid) 其实 ...

  2. 排错实战——解决c++编译错误:error C2059: illegal token on right side of '::'

    缘起 最近,项目里出现了一个奇怪的编译错误.乍看错误提示,真有丈二的和尚,摸不着头脑的感觉.解决之后,又是这么的合情合理.具体是什么样的问题呢?一起来看看吧. 说明: 实际项目中的错误隐藏的更深,完全 ...

  3. mysql5.7 1045 pc,解决MySQL5.7报错ERROR 1045 (28000): Access denied for user

    解决MySQL5.7报错ERROR 1045 (28000): Access denied for user 解决MySQL5.7报错ERROR 1045 (28000): Access denied ...

  4. 解决IntelliJ IDEA报错Error: java: 错误: 不支持发行版本 XX

    解决IntelliJ IDEA报错Error: java: 错误: 不支持发行版本 XX 解决方法 1 解决方法 2 解决方法 3   笔者在做代码重构的时候,以前记得运行正常的代码,如今一直报错,百 ...

  5. 解决IntelliJ IDEA报错Error:Cannot determine path to ‘tools.jar‘ library for 17 (C:\Program Files\Java\jd

    解决IntelliJ IDEA报错Error:Cannot determine path to 'tools.jar' library for 17 (C:\Program Files\Java\jd ...

  6. IAR STM32工程报错Error[Pe020]: identifier “GPIO_Pin_0”is undefined D:\STM32F103_Demo\App\main.c

    IAR STM32工程报错: Error[Pe020]: identifier "GPIO_Pin_0" is undefined D:\STM32F103_Demo\App\ma ...

  7. 解决Linux MySQL报错ERROR 2002 (HY000)

    ---------------------------------1--------------------------------- 在Linux安装MySQL有时候会出现[mysql]ERROR ...

  8. 解决 docker exec 报错 Error response from daemon: Container XXXXX is not running

    docker exec 报错 Error response from daemon: Container XXXXX is not running 解决思路 XXXXX 为报错容器id 问题描述 废话 ...

  9. 报错error: resource style/Theme.AppCompat.Light.DarkActionBar (aka com.xxx.xxx:style/Theme)not found.

    报错内容如下: error: resource style/Theme.AppCompat.Light.DarkActionBar (aka com.xxx.xxx:style/Theme.AppCo ...

最新文章

  1. markdown简明语法
  2. 开源项目在GitHub上贡献33.5W个Star!腾讯的十年“云”答卷,请收好!
  3. 每日站立会议12/23
  4. php 文件结尾 ?> 可以省略的情况
  5. 天底下最大的“骗子”——年龄
  6. Qt的元对象(Meta-Object)系统简介(转)
  7. 【微信小游戏实战】零基础制作《欢乐停车场》二、关卡设计
  8. 删除android电视软件下载,安卓智能电视必装工具没有之一,进程管理备份清理全靠它!...
  9. mybatis进阶--一对一查询
  10. 早期预警系统的组成要素
  11. 【读书笔记《Android游戏编程之从零开始》】15.游戏开发基础(剪切区域)
  12. PS抠发丝简单详细方法
  13. Python爬虫实战+数据分析+数据可视化(汽车之家)
  14. 2015年ps计算机试题,2015年计算机一级考试《PS》模拟试题及答案(一)(2)
  15. ubuntu系统20.04 无线网卡QCA6174 wifi不存在或找不到解决方法 红米笔记本
  16. python绘制四边形,三角形图形案例
  17. Power System中基于VIOS的虚拟以太网实现
  18. Dubbo,入门Demo案列使用,框架原理,Zookeeper的使用,安装监控中心和管理控制台,service,provider,comsumer三个项目的Demo
  19. 单源最短路径bellman算法
  20. 【图像识别】【读论文】纸币图像特征提取和识别问题

热门文章

  1. 解决高分辨率屏幕老版软件适配问题
  2. 微信小程序---数据存储
  3. VUE项目打包部署后刷新浏览器不是最新代码
  4. 军犬舆情:全流程服务打造舆情管理闭环
  5. 苹果应用商店审核_苹果应用商店审核流程更新:给开发者申诉的机会
  6. Linux镜像下载大全
  7. 【BP预测】基于差分进化算法优化BP神经网络实现汇率数据预测matlab代码​
  8. c语言实训指导书答案,《C语言程序设计》实验指导书答案
  9. 商务风团队建设与入职培训PPT模板
  10. 查看Hadoop集群的基本信息