【问题标题】:Linking error vs. compilation error链接错误与编译错误
【发布时间】:2012-11-14 09:52:58
【问题描述】:

为什么结构的双重声明会导致编译错误,而函数的双重定义会导致链接错误

【问题讨论】:

    标签: c++ c compiler-construction linker


    【解决方案1】:

    因为函数定义在链接时包含在可执行文件中,但声明或语法检查都在编译时完成

    请考虑一件事,当您调用任何函数并且编译器无法找到函数的声明时,它将生成警告为implicit declaration of func()

    为了删除这个警告信息,我们提供了 func,int func(); 的前向声明,它编译时没有任何警告信息。

    你认为为什么会发生这种情况?这是因为编译器没有找到func()symbol。这完全取决于编译器是否根据语言语法使代码无错误。

    但最终可执行文件的构建是在链接时完成的,然后链接器开始寻找 func() 的函数定义,如果找到则很好,如果没有.. 然后 Linker error

    could not have resolved external symbol _func()

    注意:任何外部符号都在链接时解析

    在 gcc 上仅用于编译使用:(这可能因编译器而异)

    gcc -Werror -c test.c --> 会生成test.o 文件

    然后尝试链接它并使其可执行

    gcc -Werror -o test test.o --> test 是可执行的

    【讨论】:

      【解决方案2】:

      标准没有说明什么时候应该报告错误——这取决于编译器,但基本上是因为那是错误被捕获的时间

      首先,编译器解析文件。很容易看出 structclass 是否在同一个翻译单元中被多次定义(只是这是一个错误,在翻译单元之间可以有多个类类型定义),因为它处理那个翻译单元。

      其次,它将目标文件链接在一起(链接)。直到现在它才能知道同一个符号被导出了多次,因为那是错误发生的时候。

      【讨论】:

        【解决方案3】:

        编译程序时,编译器需要知道要使用的结构的确切定义。但是我们只需要在尝试链接程序时才知道要使用哪个确切的功能。

        因此,如果一个结构被定义了两次,编译器会在编译过程中感到困惑,因此会在编译时报错。

        对于编译期间的函数,您可以有多个定义,但只有在链接期间才会出现混淆,因此在链接期间会报错。

        【讨论】:

          【解决方案4】:

          你说的不一定是真的。

          如果你在头文件中“内联”函数定义,然后在编译单元中写入它的定义,你会得到一个错误

          ...already has a definition.

          您所指的情况是两个不同的编译单元定义(或查看定义)相同的函数,因此在任何单个编译单元中都没有编译错误,而是它们的组合导致链接错误.

          请注意,这正是关键字inline 真正发挥作用的地方。对于头文件中定义的非模板函数,如果使用inline 关键字,则意味着定义此函数时可以存在多个编译单元。它实际上并不能保证编译器会内联它。

          【讨论】:

            猜你喜欢
            • 2020-02-17
            • 1970-01-01
            • 2012-08-01
            • 2012-07-11
            • 1970-01-01
            • 2014-01-14
            • 2014-02-26
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多