使用许多嵌套的 #include 语句对编译器错误进行故障排除

Posted

技术标签:

【中文标题】使用许多嵌套的 #include 语句对编译器错误进行故障排除【英文标题】:Troubleshooting compiler errors with many nested #include statements 【发布时间】:2018-04-24 20:36:37 【问题描述】:

我在职业生涯中使用的代码是用 C++ 编写的,并使用适用于 Visual Studio 15 的 DevEnv wrap (1.61) 构建。

大部分工作是通过一系列#include 语句配置结构,这些语句最终非常嵌套,例如:

//ObjRTC.h
struct OBJ_RTC

    OBJ_SETTINGS    settings;
    OBJ_ESTOPS      emergencyStops[maxEstops];
    OBJ_MACHINES    machines[maxMachines];
    OBJ_FOO         bar[maxFooBars];
;

.

//ObjMachines.h
struct OBJ_MACHINES

    bool    inUse;
    INPUTS  inputDevices[maxInputDevices];
    OUTPUTS outputDevices[maxOutputDevices];
;

这些结构在其他文件中进一步定义,我们开始在“def”文件中声明值。

// DefRTC.h
OBJ_RTC RealTimeController = 
    #include "DefSettings.h"
    #include "DefEstops.h"
    #include "DefMachines.h"
    #include "DefFoo.h"
;

.

// DefMachines.h

    
        true,
         /* list of inputs */ ,
         /* list of outputs */ ,
    ,
    
        true,
         /* list of inputs */ ,
         /* list of outputs */ ,
    ,
    
        true,
         /* list of inputs */ ,
         /* list of outputs */ ,
    ,
,

如果声明文件中存在语法问题,则在编译期间它通常只会被报告为来自 DefRTC.h 的最后一行。

我知道我可以开始复制文件并粘贴到 #include 行上,这是我在尝试解决问题时所做的(配置 INPUT 类型的值代替 OUTPUT

有没有办法让编译器报告语法错误来自#included 的文件?

【问题讨论】:

这些包含的数据从何而来?或许写个能生成包含文件的 import util 会更好? 可能缺少的分号实际上存在于真实代码中? 哇,真可怕。为“The Preprocessor is Evil”加注,恭喜! 啊,更正了缺少的分号。所有结构的声明和定义都在头文件中。源文件循环遍历结构以执行一些初始化(有时创建对象) 这个问题与嵌套的#include 指令无关。它与嵌套的 结构有关。如果你忘记了其中一个大括号,编译器通常无法知道,直到嵌套结构的最后,即使这样,也无法知道忘记了哪个大括号。 【参考方案1】:

您可以预处理给出编译器错误的 .c 文件并编译该预处理文件。 然后错误/警告将始终引用该文件中的一行。 然后,您可以通过插入经过预处理的书签来识别行来自的原始文件。书签基本上只是在每个文件的第一行中记录文件名。 如何制作一个预处理器幸存的书签(因为 cmets 和预处理定义当然丢失了)?

写一个typedef,它不消耗任何资源(除了命名空间使用) 它仍然存在于人眼阅读经过处理的文件:

typedef int BookmarkFilename1_h_Start;

为了方便导航,在每个标题的末尾添加另一个书签:

typedef int BookmarkFilename1_h_End;

然后,为了找到标题中的行号(如果它很长),请从 pp 文件中的错误行号中减去书签的行号(在预处理文件中)。然后在原始标题中添加书签的行号。 除了使用多行宏(\ 延续),这应该给你文件名和原始行号。

如果您的工具链/构建环境抱怨使用 int,请将其替换为任何其他已接受的可见类型。

为了重点识别可疑线路,您可以在靠近可疑线路的附近线路中添加书签。只需确保您适当地超出了任何范围,即在制作 typedef 没有问题的地方。

【讨论】:

传闻 MSVC 不会以可以编译结果的方式进行预处理。如何实现这一目标可能需要一些研究。 (传闻 gcc 和 clang 可以编译预处理)。我不想做这部分答案,因为只是听说过谣言,不想给任何编译器制造商涂黑漆。欢迎对此发表评论。

以上是关于使用许多嵌套的 #include 语句对编译器错误进行故障排除的主要内容,如果未能解决你的问题,请参考以下文章

在 IF 语句中嵌套 Case 语句

重构许多嵌套 if 或链式 if 语句

COBOL 中带有“REPLACING”的“COPY”语句

使用 FFMPEG 库时编译错误

一元二次方程 C语言IF语句嵌套问题

C #include语句在Fortran代码中做了什么? [关闭]