git 2020年项目历史记录中出现多个定义错误,现在不添加“extern”就无法构建该点之前的提交

cwxwcias  于 2023-01-04  发布在  Git
关注(0)|答案(1)|浏览(93)

我从2000年开始做的一个项目编译得很好,但有短暂的问题,可能一次提交两到三次,这种情况非常罕见。回到2020年2月,构建失败的情况如下:

/usr/bin/ld: src/dumb/frotz_dumb.a(dinit.o):/home/foobar/src/dumb/dinit.c:26: multiple definition of `f_setup'; src/common/frotz_common.a(object.o):/home/foobar/src/common/object.c:23: first defined here

通过在访问f_setup结构的源文件中将f_setup_t f_setup;的示例更改为extern f_setup_t f_setup;,很容易解决这个问题。很简单,对吧?但后来我回到2011年,当我终于开始在这个项目中使用Git时,编译失败的方式几乎相同:

gcc -O2 -DCONFIG_DIR="\"/usr/local/etc\""  -DVERSION="\"2.43\"" -DSOUND_DEV="\"\"" -DCOLOR_SUPPORT      -o src/dumb/dumb_input.o -c src/dumb/dumb_input.c
src/dumb/dumb_input.c:82:13: error: conflicting types for ‘getline’
   82 | static void getline(char *s)

我把过去两年的挫折放在一边,因为它现在构建和工作得很好,但现在我正在处理一个问题,有人提交沿着两个构建日志:一个来自最新的提交,另一个来自我上面描述的简单修复之前的提交。所以我尝试使用新用户,然后是新的Debian机器,然后是新的FreeBSD机器在这些旧提交上构建。我没有macOS机器,这是问题提交者正在使用的。这个问题严重影响了我做二分法来根除问题的能力。
我真的真的真的不想从2011年开始在这里和那里插入修复程序,从而使现有的提交哈希变得一团糟。我唯一的猜测是在2020年左右发生了什么事,在GCC中的一些默认值发生了变化。那么...到底是怎么回事?
我说的项目就在这里:https://gitlab.com/DavidGriffith/frotz/。简单修复发生在https://gitlab.com/DavidGriffith/frotz/-/commit/b001e3f64a0f223136babb228f30fcac7fe09804

pw9qyyiw

pw9qyyiw1#

C标准没有定义在多个翻译单元中使用f_setup_t f_setup;的行为。这种形式的声明被称为 * 临时定义 *,尽管它实际上不是一个定义。但是,如果在翻译单元结束之前没有看到定义,它会导致创建一个定义。
由于C语言的发展历史,这种形式的声明在不同的C实现中有不同的处理方式。2这是一个有文档记录的Unix行为,即由创建“公共”符号的临时定义创建的定义在链接过程中被合并(同一个“公共”符号的多个示例将链接到对单个实体的引用中)。因此,在头文件中使用这些声明不会导致链接器错误。在其他的C实现中,试探性的定义会创建硬引用,这会导致链接器关于多个定义的错误。因为不同的C实现对待它们的方式不同,所以C标准不需要这样或那样的行为;它没有加以界定。
在GCC版本10之前,GCC默认将暂定定义标记为“通用”符号。在GCC版本10中,默认值发生了变化。
要解决这个问题,您可以使用早于版本10的GCC版本,您可以在编译命令中添加-fcommon以选择旧的行为,或者您可以在声明中添加extern以使其成为普通的声明(不是定义,而不是试验性定义)。您需要确保在程序中的某个地方存在标识符的确切的一个定义。

相关问题