前言

VS开发中,经常遇到找不到标识符/使用未定义的结构体或者对象/无法打开包括文件,目前仅仅针对系统级别的类型声明,而不是自身声明的类型


例子1

在编译Thrift静态库,提示出错:使用未定义的 struct“timespec”

在不同的VS编译版本下,有时候也可以顺利编译通过,没有提示该错误,主要是VS2015/VS2017


例子2

编译大华SDK Demo,提示出错:CoCreateGuid 找不到标识符


例子3

编译ASIO源码,提示出错:

“signal”: 不是“`global namespace'”的成员

“signal”: 找不到标识符


例子4

无法打开包括文件: “stddef.h”: No such file or directory
无法打开包括文件: “corecrt.h”: No such file or directory
无法打开包括文件: “winapifamily.h”: No such file or directory


准备工具

VAssistX工具,可以通过GO按钮跳转到类型的声明头文件中,如果有多个声明头文件,还可以有一个列表形式可以选择,跳转到哪一个头文件


解决方案

通过GO按钮跳转到类型的声明头文件中,找到头文件所在的路径

1)尝试在代码中包含其头文件

2)在项目属性中C/C++栏目下附加包含目录

极端情况下,没有该系统库头文件,那就需要安装对应的开发SDK


原因分析

VS开发环境安装完成以后,会在系统中添加对应的SDK开发包,其中包含了相关的头文件和lib库文件,以及动态库文件。以当前开发环境为例子,同时安装了VS2015/VS2017, SDK10以上版本安装了三个,分别是

C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0

C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0

C:\Program Files (x86)\Windows Kits\10\Include\10.0.10150.0

SDK8.1版本安装了一个

C:\Program Files (x86)\Windows Kits\8.1\Include

通过对比分析,可以看到C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0文件包含的头文件是最全面的,其他的三个SDK版本,都只有部分头文件

例如,time.h文件在C:\Program Files (x86)\Windows Kits\8.1\Include中没有找到(通过Everything可以启用正则表达式(^time.h$)搜索到该信息)

time.h文件在其他三个版本的路径目录都有就在ucrt目录下。

这里面涉及到目标平台版本设置问题

如果我们设置了8.1,就会去C:\Program Files (x86)\Windows Kits\8.1\Include系统路径下,寻找其头文件,发现没有这个文件,因此直接报错


例子错误解决

解决例子1的方案是附加包含目录添加任何一个版本的SDK time.h所在的路径

解决例子2的方案是添加头文件#include <combaseapi.h>或者#include <objbase.h>

解决例子3的方案

方案一:将工程SDK切换到10.0.10240.0

方案二:C/C++常规/附加目录添加C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt

通过VAssistX的Go按钮,查看其对应的头文件所在路径和文件名称。目的平台SDK选择8.1,但是8.1SDK没有安装对应的头文件,该函数声明在signal.h文件中,但是系统安装了其他版本的SDK,在C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt路径中找到声明文件

解决例子4的方案

通过Everything工具,查找到相关头文件所在的目录,然后添加到C/C++附加包含目录

C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt 目录下存在 corecrt.h  stddef.h

C:\Program Files (x86)\Windows Kits\8.1\Include\shared 目录下存在  winapifamily.h

当前目标平台SDK选择8.1


疑惑解答

目标平台版本选择8.1,跟添加附加目录中的头文件版本10.0.10240.0不一致是否会有问题?

实际上这里面的头文件都是类型对象的声明,每一个版本的声明几乎都是一样的,只是告诉编译器这个类型在哪个文件已经声明了,类型是这个样子,因此不会影响到程序的生成。当然也可以调整目标平台版本,选择当前已经安装的完整版本的SDK