PttCurrent 板


LINE

※ 引述《knko ()》之铭言: : 我在使用kubuntu(x86_64)编译此套软体时执行pmake all install时发现错误,原因是/u : sr/bin/ld: /tmp/writemoney-42e226.o:/home/bbs/pttbbs/util/writemoney.c:5: multip : le definition of `now'; util_var.o:/home/bbs/pttbbs/util/../mbbsd/var.c:374: fir : st defined here,是於pttbbs.conf中有加入#define SHMALIGNEDSIZE (1048576*4) : #define TIMET64,似乎是爲重复定义但是我不确定是软体还是我设定的问题,我使用的版 : 本最後的编辑是https://github.com/ptt/pttbbs/commit/576513c502a9bf5fcfa08ae52ee94 : ed0c67be608 : ---- : Sent from BePTT on my Samsung SM-M127F 此问题与在 pttbbs.conf 中使用了哪些 `#define`s 无关。 「重复定义──────────────────────────────── ‧ util/writemoney.c: Line 5–6: time4_t now; // C: Tentative definition // C++: 变数定义 extern SHM_t *SHM; // 变数宣告 (建立物件) ‧ include/var.h: Line 96–100: extern time4_t now; // 变数宣告 (建立物件) extern int KEY_ESC_arg; extern int watermode ; extern int wmofo ; extern SHM_t *SHM; // 变数宣告 (建立物件) ‧ mbbsd/var.c: Line 373–375: /* io.c */ time4_t now; // C: Tentative definition // C++: 变数定义 int KEY_ESC_arg; // C: Tentative definition // C++: 变数定义 Tentative Definition ──────────────────────────────── Tentative definition 是 C 特有的概念, 指既能作宣告也能作定义函式外变数宣告或定义。 大部份的既没有使用 `extern` 没有用 `=` 初始化的函式外变数宣告/定义属於此类。 (函式没有 tentative definition,而且函式宣告预设会被视爲已有 `extern`) (注意:将 tentative definition 加上 `static` 後仍爲 tentative definition) C++ 中无此概念,这样写的宣告/定义会被视爲定义,会建立被初始化爲 0 的物件; 而要进行函式外变数宣告时,则必须使用 `extern` 关键字 (可搭配匿名 `namespace` 以限制被宣告的变数的作用域爲目前档案)。 由於 C++ 有 one definition rule,一个变数/函式在整个程式中仅能有 <= 1 个定义, 因此若编译器发现单一个「档案」(严谨地说,是 translation unit) 具有 > 1 个这样的变数定义时,会发出编译时期错误。 (上述程式码中并没有这样的问题) C 对 tentative definition 有特别的处理规则: 如果编译器编译这个档案时,未找到任何此变数的只能作定义的定义, 才会爲此宣告/定义建立物件。 建置失败的过程 ──────────────────────────────── util/writemoney.cmbbsd/var.c 间,没有一方被另一方 `#include`d 的关系; 编译器编译其中一个时,看不到另一个档案中的定义,因此并不会发出编译时期错误。 您所遇到的建置错误是连结时期错误 (link-time error), 而不是编译时期错误 (compile-time error)。 问题来了, 「重复定义」的连结 ──────────────────────────────── ‧ util/Makefile: ‧ Line 11–29: UTIL_OBJS= util_var.o # 编译後的 var.c(含有 `now` 的定义) (空行) MBBSD_OBJS= var # var.c (空行) # 下面这些程式, 会被 compile 并且和 $(UTIL_OBJS) 联结 # 联 → 连 CPROG_WITH_UTIL= \ (Line 17–20 略) toplazyBM writemoney \ # writemoney.c(含有 `now` 的定义) (Line 22–27 略) munin useractive_munin \ (空行) ‧ Line 67–70: .for fn in ${MBBSD_OBJS} # ${fn}.c == var.c util_${fn}.o: ${BBSBASE} $(SRCROOT)/mbbsd/${fn}.c # 产生 util_var.o ${CC} ${CFLAGS} -D_BBS_UTIL_C_ -c -o $@ $(SRCROOT)/mbbsd/${fn}.c .endfor ‧ Line 57–60: .for fn in ${CPROG_WITH_UTIL} # ${fn}.c 会 == writemoney.c ${fn}: ${BBSBASE} ${fn}.c ${UTIL_OBJS} # ${UTIL_OBJS} == util_var.o ${CC} ${CFLAGS} ${LDFLAGS} -o ${fn} ${UTIL_OBJS} ${fn}.c $(LDLIBS) .endfor 红色的行中,${CC} (`gcc` 或 `clang`) 会去执行编译器与连结器。 其中,连结器在连结 util_var.owritemoney.c 时, 会发现 `now` 具有两个 tentative definitions 的问题。 -fcommon & -fno-common ──────────────────────────────── `-fcommon` 选项(不可用於动态连结库 (以 `--shared` 选项编译的)) 会使编译器发现某变数具有 tentative definition(s) 但未找到只能作定义的定义时, 不直接建立对应物件,而到连结器连结时 才爲此变数的所有 tentative definition(s) 建立单一个被初始化爲 0 的对应物件。 `-fno-common` 选项(从 GCC 10 开始的预设值) 则会使编译器发现某个档案有这样的状况时, 就直接建立被初始化爲 0 的物件,使得连结器连结时发出连结时期错误。 ISO C 仅要求一个变数在整支程式中只能有 <= 1 个被初始化的定义, 但未规定 > 1 个档案具有 tentative definition(s) 时要如何处理。 因此 ISO C 并不保证这样的程式能够被正确地建置或执行; 这样的程式可能会随实际的建置环境不同,而有不同的建置或执行结果。 也就是说,在 ISO C 标准中,这会造成未定义行爲 (undefined behavior)。 只是 GCC 额外提供了编译选项,使得这种情况在标准之外变得有定义。 此外,由於 `-fcommon` 只对 tentative definition 有效, 如果 > 1 个档案具有只能作定义的定义,或是以 C++ 模式编译的话, 使用 `-fcommon` 选项编译并无法避免连结时期错误。 ※ 引述《holishing ( )》之铭言: : 新版的 gcc 会严格限制 multiple definition : 所以在 Ubuntu Focal 或 Debian Bullseye 会遇到编译错误 (以前只会警告) : 两种解法: : 第一种是在编译参数加上 -fcommon (让它允许重复定义) : 第二种是把重复定义删掉,例如参考以下修改: : https://github.com/bbsdocker/imageptt/blob/87c0ec3c/multipledef.patch : 应该就可以编译过了 根本的解决方法 ──────────────────────────────── 1. 直接移除此 tentative definition。 ‧ 因已由 `#include "bbs.h"` → `#include "var.h"` 引入宣告, 此 tentative definition 并非必要。 2. 若要保留此宣告,须加上 `extern`: ‧ util/writemoney.c: Line 5–6: - time4_t now; // C: Tentative definition // C++: 定义 + extern time4_t now; // 宣告 (不建立物件) extern SHM_t *SHM; // 宣告 (建立物件) 爲什麽使用了 tentative definition? ──────────────────────────────── 在 ISO C89 以前,C 没有 `extern` 可用,只能用此方法进行前向变数宣告; 而 ISO C89 引入 `extern` 後,爲了维持向旧相容,才引入了这项规则。 见 https://en.cppreference.com/w/c/language/extern 或许 writemoney.c 中的 `now` 的 tentative definition 的意图是进行变数宣告。 也或许只是因爲当时的编译器不会提出错误讯息,所以才没有加上 `extern`。 ‧ Google 搜寻在 1997 年推出(当时最流行的浏览器是 Netscape Navigator)https://web.archive.org/web/19981111183552/http://google.stanford.edu/ ‧ Wikipedia 在 2001 年推出(最流行 Microsoft Internet Explorer 5https://web.archive.org/web/20010727112808/http://www.wikipedia.org/ ‧ cppreference.com 也在 2001 年推出: https://web.archive.org/web/20010223150424/http://www.cppreference.com/writemoney.c 是在 2005 年撰写的(最流行 Microsoft Internet Explorer 6)https://github.com/ptt/pttbbs/blob/814f94b737/util/writemoney.c 当时使用浏览器浏览网页,甚至使用搜寻引擎,或许还不是很流行的事情。 当时的开发者或许没有如 cppreference.com 般唾手可得的语言标准参考资料能够参考。 话虽如此,以上也只是对 16 年前的情况的猜测。也许眞相早已随着时光而流逝。 --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 140.116.130.29 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/PttCurrent/M.1640012985.A.9F7.html 简言之: UTIL_OBJS= util_var.o # applepen CPROG_WITH_UTIL= \ toplazyBM writemoney \ # pineapplepen ${CC} ${CFLAGS} ${LDFLAGS} -o ${fn} ${UTIL_OBJS} ${fn}.c $(LDLIBS) # PENPINEAPPLEAPPLEPEN ※ 编辑: IepID (140.116.130.29 台湾), 12/20/2021 23:24:55 ※ 编辑: IepID (140.116.130.29 台湾), 12/20/2021 23:29:24 ※ 编辑: IepID (140.116.130.29 台湾), 12/20/2021 23:36:32 ※ 编辑: IepID (140.116.130.29 台湾), 12/20/2021 23:44:26 ※ 编辑: IepID (140.116.130.29 台湾), 12/20/2021 23:46:00







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Gossiping站内搜寻

TOP