8

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

标志 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 上编译,如果版本不兼容?

4

6 回答 6

11

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

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

编辑:

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

于 2013-03-05T15:44:02.713 回答
5

这是重复的:为什么在 GCC 4.3 而不是 GCC 4.6 中出现“重新定义 typedef”错误?

答案是更改了 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

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

于 2013-03-24T12:26:47.280 回答
4

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

于 2013-03-12T08:07:51.057 回答
1

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

typedef struct Foo* Fooptr;

在头文件中,然后:

typedef struct Foo
{
    int bar;
} *Fooptr;

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

现在,如果这一个gcc问题,解决您的问题的第二个选项是,可以在同一台计算机上拥有多个版本的 gcc,然后gcc通过该-v选项指定要运行的确切版本。因此,在您的 Fedora 18 机器上试一试 4.1.2 可能是个好主意。

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


好的,现在开始你的问题。是的,有用于在“版本 X”上编译的标志gcc:对于初学者来说,有__VERSION__预定义宏,这将向你吐出const char *版本号。这可能非常有用,但正如 gcc 文档所述:

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

尽管如此,我通常只看到一种形式的输出,这就像"4.6.3"我的版本gccis 4.6.3-1ubuntu5

现在,如果您知道(或怀疑)您的某些代码会导致特定版本的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.xx”消息。然后您可以更高级并检查颠覆:

#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 代码创建了一个部分,便于查看。

于 2013-03-22T12:46:49.907 回答
1

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

有没有我可以设置的标志来避免将来发生这种情况。

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

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

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

于 2013-03-27T15:03:24.413 回答
1

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

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

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

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

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

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

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

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

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

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

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

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

于 2013-03-22T17:02:12.720 回答