【问题标题】:How to track down cause of missing struct from include files in C?如何从 C 中的包含文件中查找缺少结构的原因?
【发布时间】:2009-07-01 05:08:15
【问题描述】:

我正在移植一个相当大的项目,并且在许多标题之一中,我包含了一个包含 pmc_mdep 结构定义的文件。 (之前在文件中它刚刚声明,但后来它实际定义)。

尝试编译它会给我关于该结构是不完整类型的错误(我认为这意味着它缺少定义)。

当我在这个项目上运行预处理器时,它确实包含该文件,但预处理器输出没有结构定义(但包含该文件中的枚举)。

有没有办法弄清楚为什么有些头文件会到达预处理器输出,而有些却没有?

TIA

(另外,这不是唯一的编译错误,端口已经完成了一半,但至少应该可以通过这部分)

【问题讨论】:

    标签: c struct header


    【解决方案1】:

    我通常只是从结构中追溯,以找到预处理器将遇到的所有封闭的"#ifdef""#if" 行,并查看哪一个控制着将结构从输入流中删除到编译器中。

    这通常对除了最复杂的头文件(即具有大量嵌套条件编译语句的头文件)之外的所有头文件都非常有效。对于这些,我通常会查看预处理器的输出,以识别头文件中的最后一行进入编译器输入流。

    几乎可以肯定,下一行将是一个条件编译语句,您尚未满足包含条件。

    例如,如果this 是头文件,则需要回溯以查看应定义_KERNEL 以获得声明和定义。

    【讨论】:

    • :-) 你抓住了我;我确实将 hwpmc 内核模块从 FreeBSD 移植到 Minix。并且_KERNEL在树顶部的头文件中定义为1(我写的)
    • 但是,IIRC,声明和定义都在该文件中使用 _KERNEL 进行了 ifdef。您是说声明在预处理器输出中,但定义不是?您可能需要仔细查看预处理器输出(我的答案的第 2 和第 3 段)以确定问题。
    • 哎哟!这是 KERNEL 定义...我在 _after 包含整个标题树之后定义了它。
    • C'est la vie,我想这就是我们学习的方式。我的教育经历要痛苦得多 :-) 很高兴能提供帮助。
    【解决方案2】:

    恐怕不会;您将不得不寻找围绕您感兴趣的区域的#ifdefs,并找出未定义这些符号的原因。如果它正在移植到 Linux/UNIX 并且您缺少标准头文件中的内容,那么您可能没有在 Makefile 或 config.h 中定义正确的 _XOPEN_SOURCE 或 _BSD_SOURCE 。

    【讨论】:

      【解决方案3】:

      最可能的原因是定义周围有一个#define。由于相应的符号未定义或定义为其他值,因此即使包含标头本身,也不包含定义。您必须手动检查。

      【讨论】:

        【解决方案4】:

        Raymond Chen 对此有一个blog post

        您可能会发现自己陷入了#ifdefs 的曲折迷宫。或者您可能想知道为什么您的宏不起作用。

        我的头文件中有这些行:

        #define MM_BUSY     0x0001
        #define MM_IDLE     0x0002
        

        但是当我尝试使用它们时,我得到了错误。

        sample.cpp(23): error C2065: 'MM_BUSY': undeclared identifier
        sample.cpp(40): error C2065: 'MM_IDLE': undeclared identifier
        

        知道为什么会这样吗?

        解决方案:使用#error 来追踪问题,就像你分散printf 来追踪常规错误一样。

        来源: Use the #error directive to check whether the compiler even sees you

        【讨论】:

        • 嗯...他已经知道编译器看不到他的代码。问题是如何让编译器告诉它为什么看不到它。
        • 尽管如此,我仍然得到了加分,因为我不知道你怎么能把'printf's 来检查预处理器。谢谢!
        【解决方案5】:

        我认为除了检查预处理器输出以了解为什么包含一个文件之外,没有更好的方法。 Here 是 gcc 的预处理器的输出格式,可以帮助你理解预处理器的输出。

        另外,您可以尝试比较您正在移植的输出与现有输出之间的另一种方法。

        【讨论】:

        • 感谢您的回答。我对格式有相当好的掌握(在调试过程中阅读了很多格式),但我以前从未有过参考。谢谢!
        【解决方案6】:

        你说:

        我正在移植一个相当大的项目,并且在许多标题之一中,我包含了一个包含 pmc_mdep 结构定义的文件。 (之前在文件中它刚刚声明,但后来它实际定义)。

        尝试编译它会给我关于该结构是不完整类型的错误(我认为这意味着它缺少定义)。

        如果您在完全定义 pmc_mdep 之前尝试将 pmc_mdep 嵌入到其他结构中,则可能会出现此错误。请注意,您可以将指向不完整类型的指针嵌入到结构中,但不能将不完整类型的实际实例嵌入到结构中。

        您还讨论了在应该定义结构的文件上运行预处理器,并且您看到枚举形成了标题,但没有看到结构定义。这表明您可能有一个无意中删除结构的杂散注释,或者您可能在#ifdef XXX#endif 之间嵌入了结构定义,但在您进行编译时未定义XXX。甚至可以是#if 0

        我会在包含结构定义的标头上运行 C 预处理器,看看会产生什么;它比尝试查看整个程序(源文件)的输出要短。如果我不能迅速发现问题,我会用诸如杂散枚举之类的东西标记部分,看看哪些能通过,哪些不能通过。

        【讨论】:

        • 这是我最初的想法,但错误发生在几个文件之后。我假设如果问题是在定义之前引用它的原始文件,那就是错误所在。
        猜你喜欢
        • 1970-01-01
        • 2010-09-08
        • 1970-01-01
        • 2015-06-17
        • 2018-06-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多