【问题标题】:compiling source code on 2 different versions of gcc在 2 个不同版本的 gcc 上编译源代码
【发布时间】:2013-02-19 18:36:09
【问题描述】:

我正在使用不同版本的 gcc 的 2 台不同的机器上编译我的源代码。

cflags c89

-Wall -Wextra -Wunreachable-code -g -m32 -D_DEBUG -O0 -D_LARGEFILE64_SOURCE -D_REETRANT -D_THREAD_SAFE

一个是redhat-4

gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46)
Linux 203_test_server 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:48 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux

还有一个是 Fedora 18

gcc (GCC) 4.7.2 20121109 (Red Hat 4.7.2-8)
Linux localhost.localdomain 3.8.1-201.fc18.x86_64 #1 SMP Thu Feb 28 19:23:08 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

我的 fedora 18 编译没有错误。但是,在 redhat 4 机器上我得到了一些错误。

channel.h:35: error: redefinition of typedef ‘channel_t’
internal.h:19: error: previous declaration of ‘channel_t’ was here

我认为错误只是一个循环问题。但是,如果使用相同的代码库,在 2 台不同的机器上编译,使用 2 种不同版本的 gcc 真的会有所不同吗?

我在想使用较新版本的编译器会产生更多错误,因为较新的编译器可能更严格。

这不是解决错误的问题,而是关于编译器的一般问题。

我可以设置任何标志来避免将来发生这种情况。也许如果在这个版本的 gcc 上编译,如果版本不兼容?

【问题讨论】:

  • 是的,不同的编译器/版本/标志可能会产生不同的结果,尤其是。在#ifdef-heavy 代码中。
  • 至于any flags I can set to avoid this in the future,我的回答是否涵盖了这一点,还是您在想一些不同的东西?
  • 一些有用的信息会很好,它更有可能是一个系统上的包含头文件,而不是编译器,但你永远不会提到 channel.h 或 internal.h 的位置或它们是如何被包含的。 channel_t 出现的周围的线条也很有用……至少对 ifdefs 来说是这样。没有它,您的 CFLAG 定义就毫无意义。

标签: c gcc


【解决方案1】:

这取决于源代码包含哪些标头。如果您要链接到外部库,则可能是您的源代码与安装在旧系统上的库版本不兼容。

如果源代码不包含任何外部库头文件(C 库除外),则可能存在需要更改的预处理器指令。

编辑:

Google 搜索后,channel_t 似乎来自内核标头。您在两台机器上使用相距很远的内核版本。如果代码依赖于内核头文件,它可能需要比 Red Hat 机器上的内核版本更新。您还没有指定代码是什么(它是设备驱动程序吗?),或者它包含哪些文件,所以很难说更多。

【讨论】:

    【解决方案2】:

    这是一个重复的:Why "Redefinition of typedef" error with GCC 4.3 but not GCC 4.6?

    答案是修改了gcc来修改这个检查。

    http://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=ce3765bf44e49ef0568a1ad4a0b7f807591d6412

    有时,由于某些有用和/或无害的用例包含在警告中,因此语言中定义但被认为是不良做法的行为警告被认为过于严格。然后编译器开发人员尝试以相反的方式进行修复,即减少警告的数量。在这种情况下,只有在第二个定义将 typedef 更改为不同但兼容的类型时,才会出现警告。

    其他当前示例是刚刚宣布的 gcc 4.8 中的 -Wshadow。在发行说明中,它说如果一个函数名被另一个函数名遮蔽,-Wshadow 将不再发出警告。

    见: http://gcc.gnu.org/gcc-4.8/changes.html

    编辑:如何避免这种情况:要么删除其中一个定义,要么将其移至单独的包含文件并删除其他两个定义。

    【讨论】:

      【解决方案3】:

      在您得到不同结果的两个系统上比较 channel.h 和 internal.h 的内容。我怀疑问题出在 gcc 的版本上。错误更有可能是这些文件的代码随着时间的推移而更改的结果,例如当一个系统具有比另一个系统更新版本的库和相关的头文件时。

      【讨论】:

        【解决方案4】:

        首先,让我们稍微谈谈您的问题。我认为您的系统在一个系统上出现错误的最可能原因是代码不相同;您可能想通过一些工具或diff 命令来验证这一点,以查找代码库中出现的任何细微变化。 通常,当我看到与该错误类型有关的问题时,您会遇到如下情况:

        typedef struct Foo* Fooptr;
        

        在头文件中然后:

        typedef struct Foo
        {
            int bar;
        } *Fooptr;
        

        在源文件中。这意味着您可以将 typedef 放在源代码中,它应该没问题。只是要寻找的东西。

        现在如果它 gcc 问题,解决您的问题的第二个选项是,可以 have multiple versions of gcc on the same computer 然后指定 gcc 的确切版本以通过 via 运行-v 选项。因此,在您的 Fedora 18 机器上试一试 4.1.2 可能是个好主意。

        另外注意,如果您使用-v 选项,但指定要运行的gcc 版本,您将获得(在标准错误输出上)执行的命令以运行编译阶段。这对于查看正在发生的事情以及每台机器上发生的事情之间是否存在任何重大差异可能很有用。


        好的,现在回答你的问题。是的,gcc 的“版本 X”上有编译标志: 对于初学者,有__VERSION__ Predefined Macro,这将向您吐回版本号的const char *。这可能非常有用,但正如 gcc 文档所述:

        您不应依赖其内容具有任何特定形式,但可以指望它至少包含版本号

        尽管如此,如果我的gcc 版本是4.6.3-1ubuntu5,我通常只看到一种形式的输出,类似于"4.6.3"

        现在,如果您知道(或怀疑)您的某些代码会导致特定版本的 gcc 导致错误,您可以使用 __GNUC____GNUC_MINOR____GNUC_PATCHLEVEL__ 预定义宏来“保护”你自己:
        这是一个简短的片段,它以最高级别展示了如何使用它:

        #if __GNC__ == 3
            printf(“Hello version 3.x.x\n”);
        #elif __GNC__ == 4
            printf(“Hello version 4.x.x\n”);
        #endif
        

        因此,在上述版本为 4.6.3 的系统上,您会看到“Hello version 4.x.x”消息。然后你可以更高级并检查颠覆:

        #if __GNUC__ > 3 || \
            (__GNUC__ == 3 && (__GNUC_MINOR__ > 2 || \
                (__GNUC_MINOR__ == 2 && \
                  __GNUC_PATCHLEVEL__ > 0))
            printf(“I’m a gcc greater than 3.2.0\n”);
        #endif
        

        或者使用您自己的宏的更简洁的版本:

        #define GCC_VERSION (__GNUC__ * 10000 \
            + __GNUC_MINOR__ * 100 \
            + __GNUC_PATCHLEVEL__)
        #if GCC_VERSION > 30200
            printf(“I’m a gcc greater than 3.2.0\n”);
        #endif
        

        为了解决您关于gcc 的不同版本是否会产生不同错误的问题,您是正确的,在gcc 的每个版本中都会发生更多事情,有时情况确实会发生变化,因此您会看到不同版本之间的差异的编译器。最好的办法是检查您所使用的两个版本之间的每个版本的发行说明。 (从 4.1 到 4.7)。

        我不确定您的目标架构是什么,因此请务必检查每个文档中的特定部分。但我认为你真的很想看看"Build system improvements""Incompatible changes to the build system",它们还专门针对C 代码做了一个部分,便于查看。

        【讨论】:

          【解决方案5】:

          这里没有足够的信息来准确说明发生了什么。我同意那些说这不太可能是编译器版本问题的人。

          当编译器遇到两个相同名称的不同声明时,会发生此错误(显然)。弄清楚为什么会发生这种情况应该不难。

          检查 makefile 以查找被引用的 internal.hchannel.h 头文件。引用的行将有一个typedef 或其他channel_t 的声明。从这些声明中向外寻找线索。

          我必须假设这些文件中的一个或两个都在您正在使用的库中。如果internal.hchannel.h都是你自己的代码,调试你自己的代码!

          否则有很多可能性。最有可能的是

          1. 预处理器-D#defineed 标志不正确,因此当只有一个声明时,多个声明被条件编译。

          2. 两个不同的库或标准头文件和一个库有名称冲突。

          3. 您自己的代码与库或标准头文件发生冲突。如果channel_t 是您定义的类型,那就有问题了。您不应定义自己的以_t 结尾的类型,因为这些类型是为实现保留的。

          上述第 1 条可能以多种方式出现,但最常见的是库配置错误。对于正在使用的操作系统,库通常必须是./configureed。如果您在一个 Linux 中进行配置并复制到另一个 Linux,那么您会遇到与您所看到的类似的问题。

          由于库版本差异,第 2 个可能出现在一个 linux 上,而不是另一个。在这种情况下,请将有错误的机器更新到与没有错误的机器相同的版本。不要忘记运行./configure

          对于 3 号,修复是显而易见的。更改您的类型名称。

          我在 Tor 中看到了 channel.hchannel_t。我的疯狂猜测是,您正在使用 Tor 并查看机器上的 Tor 配置错误。

          【讨论】:

            【解决方案6】:

            这不是解决错误的问题,而是关于 编译器。

            我是否可以设置任何标志来避免将来发生这种情况。

            每个特定版本的编译器都有自己的开关或标志。

            如果创建编译器版本以接受某些开关,并且其中一个是您需要避免对源代码进行某些检查的开关,那么是的,将来有/将有一种方法可以避免它。

            如果您正在使用的编译器版本、最近或未来版本没有/接受一个开关来避免/跳过对您的源代码的某些检查,那么就没有办法避免它。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-01-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-02-19
              • 1970-01-01
              相关资源
              最近更新 更多