- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我尝试构建一个链接到各种共享库和静态库的可执行文件。事实证明,两个静态库都定义相同的符号,这会导致多定义链接器错误。我的可执行文件不使用此符号,因此它并不是真正的问题。
我可以通过添加--allow-multiple-definitions
标志来避免该错误,但这似乎是一个核选项。如果我尝试使用多次定义的符号,我希望链接器抱怨。
有没有办法告诉链接器“仅在使用符号的情况下才对多个定义进行抱怨”?或者,也可以告诉它“从lib ABC忽略符号XYZ”。我正在Linux上使用g++进行开发。
最佳答案
您可能有一个问题的变体或另一个变体,
取决于您尚未考虑的相关事实。或者,可能您将两者混合使用,所以我将逐步介绍每种变体的解决方案。
您应该熟悉静态库的性质以及如何在链接中使用它们,
as summarised here
多余的全局符号变体
这是几个源文件和头文件:
one.cpp
#include <onetwo.h>
int clash = 1;
int get_one()
{
return clash;
}
#include <onetwo.h>
int get_two()
{
return 2;
}
#pragma once
extern int get_one();
extern int get_two();
libonetwo.a
中
$ g++ -Wall -Wextra -pedantic -I. -c one.cpp two.cpp
$ ar rcs libonetwo.a one.o two.o
onetwo.h
中定义
libfourfive.a
中,该API的预期API
fourfive.h
中定义
#include <fourfive.h>
int clash = 4;
int get_four()
{
return clash;
}
#include <fourfive.h>
int get_five()
{
return 5;
}
#pragma once
extern int get_four();
extern int get_five();
#include <onetwo.h>
#include <fourfive.h>
int main()
{
return get_one() + get_four();
}
$ g++ -Wall -Wextra -pedantic -I. -c prog.cpp
$ g++ -o prog prog.o -L. -lonetwo -lfourfive
/usr/bin/ld: ./libfourfive.a(four.o):(.data+0x0): multiple definition of `clash'; ./libonetwo.a(one.o):(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
clash
的名称冲突,因为它是在两个
one.o
和
four.o
:
$ readelf -s libonetwo.a libfourfive.a | egrep '(File|Symbol|OBJECT|FUNC)'
File: libonetwo.a(one.o)
Symbol table '.symtab' contains 11 entries:
9: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 clash
10: 0000000000000000 16 FUNC GLOBAL DEFAULT 1 _Z7get_onev
File: libonetwo.a(two.o)
Symbol table '.symtab' contains 10 entries:
9: 0000000000000000 15 FUNC GLOBAL DEFAULT 1 _Z7get_twov
File: libfourfive.a(four.o)
Symbol table '.symtab' contains 11 entries:
9: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 clash
10: 0000000000000000 16 FUNC GLOBAL DEFAULT 1 _Z8get_fourv
File: libfourfive.a(five.o)
Symbol table '.symtab' contains 10 entries:
9: 0000000000000000 15 FUNC GLOBAL DEFAULT 1 _Z8get_fivev
clash
中未引用问题符号
prog.(cpp|o)
。您想知道:
Is there a way to tell the linker "complain for multiple definitions only if the symbol is used"?
one.o
中提取
libonetwo.a
并链接到程序(如果链接程序不需要它来解析某些符号)。需要它
get_one
。同样,它仅链接了
four.o
,因为解析
get_four
时需要使用它。
clash
的冲突定义在链接中。尽管
prog.o
不使用
clash
,
get_one
,后者使用
clash
,并且打算在
clash
中使用
one.o
的定义。
prog.o
使用
get_four
,后者使用
clash
并打算在
four.o
中使用不同的定义。
clash
,它的定义事实
--allow-multiple-definitions
允许。
Or alternatively [is there a way to] tell it, "from lib ABC ignore symbol XYZ".
clash
的定义
four.o
中并将符号解析为
one.o
(唯一的其他候选者)中的定义,然后
get_four()
将在我们的程序中返回1而不是4。那
--allow-multiple-definitions
的效果,因为它导致了第一个定义
libonetwo.a
(或
libfourfive.a
)的源代码,我们可以相当自信地发现根
clash
已留有外部链接,其中
#include <onetwo.h>
namespace {
int clash = 1;
}
int get_one()
{
return clash;
}
#include <fourfive.h>
namespace {
int clash = 4;
}
int get_four()
{
return clash;
}
$ g++ -Wall -Wextra -pedantic -I. -c one_good.cpp four_good.cpp
$ readelf -s one_good.o four_good.o | egrep '(File|Symbol|OBJECT|FUNC)'
File: one_good.o
Symbol table '.symtab' contains 11 entries:
5: 0000000000000000 4 OBJECT LOCAL DEFAULT 3 _ZN12_GLOBAL__N_15clashE
10: 0000000000000000 16 FUNC GLOBAL DEFAULT 1 _Z7get_onev
File: four_good.o
Symbol table '.symtab' contains 11 entries:
5: 0000000000000000 4 OBJECT LOCAL DEFAULT 3 _ZN12_GLOBAL__N_15clashE
10: 0000000000000000 16 FUNC GLOBAL DEFAULT 1 _Z8get_fourv
$ g++ -o prog prog.o one_good.o four_good.o
$./prog; echo $?
5
objcopy
。
$ objcopy --localize-symbol=clash libonetwo.a libonetwo_good.a
$ objcopy --localize-symbol=clash orig.o fixed.o
libonetwo(orig.o)
上输出固定的目标文件
fixed.o
,
fixed.o
文件归档到新的静态库
libonetwo_good.a
中。和
--localize-symbol=clash
对每个目标文件的作用是更改
clash
(如果已定义),从外部(
GLOBAL
)到内部(
LOCAL)
:
$ readelf -s libonetwo_good.a | egrep '(File|Symbol|OBJECT|FUNC)'
File: libonetwo_good.a(one.o)
Symbol table '.symtab' contains 11 entries:
9: 0000000000000000 4 OBJECT LOCAL DEFAULT 3 clash
10: 0000000000000000 16 FUNC GLOBAL DEFAULT 1 _Z7get_onev
File: libonetwo_good.a(two.o)
Symbol table '.symtab' contains 10 entries:
LOCAL
中看到
clash
的
libonetwo_good.a(one.o)
定义。
libfourfive.a
具有
$ objcopy --localize-symbol=clash libfourfive.a libfourfive_good.a
prog
。
$ g++ -o prog prog.o -L. -lonetwo_good -lfourfive_good
$ ./prog; echo $?
5
libonetwo.a
的源和 header 是:
#include <onetwo.h>
#include "priv_onetwo.h"
int inc_one()
{
return inc(clash);
}
#include <onetwo.h>
#include "priv_onetwo.h"
int inc_two()
{
return inc(clash + 1);
}
#include "priv_onetwo.h"
int clash = 1;
int inc(int i)
{
return i + 1;
}
#pragma once
extern int clash;
extern int inc(int);
#pragma once
extern int inc_one();
extern int inc_two();
libfourfive.a
,它们是:
#include <fourfive.h>
#include "priv_fourfive.h"
int dec_four()
{
return dec(clash);
}
#include <fourfive.h>
#include "priv_fourfive.h"
int dec_five()
{
return dec(clash + 1);
}
#include "priv_fourfive.h"
int clash = 4;
int dec(int i)
{
return i - 1;
}
#pragma once
extern int clash;
extern int dec(int);
#pragma once
extern int dec_four();
extern int dec_five();
priv_onetwo.cpp
|
priv_fourfive.cpp
)
priv_onetwo.h
|
priv_fourfive.h
)-不随库一起分发。
UND
)引用
clash
:
$ readelf -s libonetwo.a libfourfive.a | egrep '(File|Symbol|OBJECT|FUNC|clash)'
File: libonetwo.a(one.o)
Symbol table '.symtab' contains 13 entries:
9: 0000000000000000 23 FUNC GLOBAL DEFAULT 1 _Z7inc_onev
10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND clash
File: libonetwo.a(two.o)
Symbol table '.symtab' contains 13 entries:
9: 0000000000000000 26 FUNC GLOBAL DEFAULT 1 _Z7inc_twov
10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND clash
File: libonetwo.a(priv_onetwo.o)
Symbol table '.symtab' contains 11 entries:
9: 0000000000000000 4 OBJECT GLOBAL DEFAULT 2 clash
10: 0000000000000000 19 FUNC GLOBAL DEFAULT 1 _Z3inci
File: libfourfive.a(four.o)
Symbol table '.symtab' contains 13 entries:
9: 0000000000000000 23 FUNC GLOBAL DEFAULT 1 _Z8dec_fourv
10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND clash
File: libfourfive.a(five.o)
Symbol table '.symtab' contains 13 entries:
9: 0000000000000000 26 FUNC GLOBAL DEFAULT 1 _Z8dec_fivev
10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND clash
File: libfourfive.a(priv_fourfive.o)
Symbol table '.symtab' contains 11 entries:
9: 0000000000000000 4 OBJECT GLOBAL DEFAULT 2 clash
10: 0000000000000000 19 FUNC GLOBAL DEFAULT 1 _Z3deci
#include <onetwo.h>
#include <fourfive.h>
int main()
{
return inc_one() + dec_four();
}
$ g++ -Wall -Wextra -pedantic -I. -c prog.cpp
$ g++ -o prog prog.o -L. -lonetwo -lfourfive
/usr/bin/ld: ./libfourfive.a(priv_fourfive.o):(.data+0x0): multiple definition of `clash'; ./libonetwo.a(priv_onetwo.o):(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
clash
再次被乘法定义。要在
inc_one
中解析
main
,
one.o
,这使其不得不解析
inc
,这使得它需要
priv_onetwo.o
,其中包含
clash
的第一个定义。要在
dec_four
中解析
main
,
four.o
,这使其不得不解析
dec
,这使得它需要
priv_fourfive.o
,其中包含
clash
的竞争定义。
clash
具有外部链接不是两个库中的编码错误。
clash
本地化
objcopy
的定义
libonetwo.a(priv_onetwo.o)
或
libfourfive.a(priv_fourfive.o)
将不起作用。如果我们这样做
clash
到另一个目标文件中存在的一个
GLOBAL
定义:然后是
dec_four()
将在程序中返回0而不是3,
dec_five()
将返回1而不是4;否则
inc_one()
将返回5,而
inc_two()
将返回6。
clash
的定义。
prog
以满足
one.o
或
four.o
中的引用,并且对
clash
的 undefined reference 将失败
objcopy
再次得到救援,但是具有不同的选项1:
$ objcopy --redefine-sym clash=clash_onetwo libonetwo.a libonetwo_good.a
libonetwo_good.a
,
libonetwo.a
中成对相同的新对象文件,
clash
已经到处都被
clash_onetwo
代替:
$ readelf -s libonetwo_good.a | egrep '(File|Symbol|clash)'
File: libonetwo_good.a(one.o)
Symbol table '.symtab' contains 13 entries:
10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND clash_onetwo
File: libonetwo_good.a(two.o)
Symbol table '.symtab' contains 13 entries:
10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND clash_onetwo
File: libonetwo_good.a(priv_onetwo.o)
Symbol table '.symtab' contains 11 entries:
9: 0000000000000000 4 OBJECT GLOBAL DEFAULT 2 clash_onetwo
libfourfive.a
进行相应的操作:
$ objcopy --redefine-sym clash=clash_fourfive libfourfive.a libfourfive_good.a
$ g++ -o prog prog.o -L. -lonetwo_good -lfourfive_good
$ ./prog; echo $?
5
objcopy
与任何选项参数一起使用,请不要忘记
clash
也是
clash
。但是如果完全合格的识别者
onetwo::clash
所示,其错误名称为
_ZN6onetwo5clashE
,由
nm
或
readelf
。相反,如果您希望使用objcopy来更改
_ZN6onetwo5clashE
,
onetwo::klash
分解,然后该符号将
_ZN6onetwo5klashE
。
关于c++ - 不使用重新定义的符号时避免多定义链接器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61663118/
这个问题在这里已经有了答案: How does Scala's apply() method magic work? (3 个回答) 9年前关闭。 假设我在 scala 中有一个 MyList 类,其
这个问题在这里已经有了答案: What is a non-capturing group in regular expressions? (18 个回答) Reference - What does
这个问题是针对嵌入式系统的! 我有以下选项来初始化一个对象: Object* o = new Object(arg); 这会将对象放入堆中并返回指向它的指针。我不喜欢在嵌入式软件中使用动态分配。 Ob
我自己搜索过,没能成功的正则表达式。 我有一个 html 文件,其中包含 [] 之间的变量我想把每一个字都写进去。 [client_name][client_company] [cl
我是 Python 新手。我不明白为什么这段代码不起作用: reOptions = re.search( "[\s+@twitter\s+(?P\w+):(?P.*?)\s+]", d
在过去 7 个月左右的时间里,我几乎一直在使用 .NET C# 进行编程。在那之前,我的大部分编程都是用 C++(从学校里学的)。在工作中,我可能需要在接下来的几个月里做一大堆 C 语言。我对 C 的
我是 RE 的新手,我正在尝试获取歌词并分离出歌词标题、和声和主唱: 下面是一些歌词的例子: [Intro] D.A. got that dope! [Chorus: Travis Scott] Ic
这可能是不可能的,但我想检查是否可以用一种简单的方式表达这样的事情: // obviously doesn't work class Foo : IFoo where T: Bar {
我们的应用程序中有“user”和“study”实体,存储在它们各自的表中。一项研究代表一种研究和已收集的数据。它们是多对多的关系,所以我们需要一个链接表:studies_users。 我们为用户分配角
将测试条件添加到 Visual Studio 2010 数据库单元测试(对于 SQL Server 2008)时,这些条件称为例如rowCountCondition1、rowCountConditio
在模拟器上,我可以从设置中卸载 SD 卡。 然后我可以将它安装到我的操作系统上,然后正常卸载它。 我一直无法弄清楚如何在模拟器上重新安装它(无需重新启动)。 提示: adb 命令 remount 是无
假设在一个分支上执行了一系列提交,但该分支尚未与主干重新同步。是否可以从提交中生成全局补丁?是否可以从一系列提交中生成“分组”补丁?如果是,如何? 最佳答案 svn diff -rXXX:YYY UR
在某些情况下,我想在我的应用程序中锁定调整大小功能,为此我尝试对属性进行数据绑定(bind),并且不允许在某些情况下更改它,但没有成功。 有没有办法这样做? 这是我不成功的尝试: XAML: Vie
当我的计算机连接多个显示器时,我可以检测它们,并根据从获取的值设置位置来向它们绘制图形 get(0, 'MonitorPositions') 但是,当我在 MATLAB 运行时断开监视器时,此属性不会
我们有一个grails应用程序,该应用程序在grails数据库中存储了各种域对象。该应用程序连接到第二个数据库,运行一些原始sql,并在表中显示结果。它基本上是一个报告服务器。 我们通过在DataSo
无法比较来自不同容器的迭代器(参见这里的示例: https://stackoverflow.com/a/4664519/225186 )(或者从技术上讲,它不需要有意义。) 这就提出了另一个问题,来自
我有以下情况: 家长 Activity : ParentActivityClass { private Intent intent; @Override public void onCreate(Bu
我经常将元素与附加功能 Hook ,例如: $('.myfav').autocomplete(); $('.myfav').datepicker(); $('.myfav').click(somefu
因此,我将 tooltipster.js 库用于工具提示,并尝试更改工具提示在不同屏幕尺寸上的默认距离。 所以这是默认的 init 的样子: $(inputTooltipTrigger).tool
我在 ARM7 嵌入式环境中工作。我使用的编译器不支持完整的 C++ 功能。它不支持的一项功能是动态类型转换。 有没有办法实现dynamic_cast<>() ? 我使用 Google 寻找代码,但到
我是一名优秀的程序员,十分优秀!