g++链接错误-解决方法有效的原因
A g++ link error - why the workaround works
我正在做一个大项目。现在遇到链接错误
这个错误可以通过一个变通方法来避免,但我不明白它为什么有效。
以下是与我的问题相关的文件结构:
项目|-软件包a|--a.cpp|--。。。|-软件包b|--b.cpp|--c.cpp|--。。。|-其他软件包
package_a中的所有*.o将打包到package_b中的a.a和*.o将装入b.a
"g++ -o exec -Bstatic b.a a.a ..."
用于生成二进制文件。
在package_b/b.cpp中,我添加了一个函数foo((
在package_a/a.cpp中,我使用了这个函数
但这里我会得到一个链接错误,说a.o中foo((的未定义引用
我可以(通过objdump(验证foo((已经在b.o.中
通过将link命令更改为"g++ -o exec -Bstatic a.a b.a ..."
,可以成功构建二进制文件。我现在明白了链接器确实关心链接列表中的顺序。但请理解这是一个大项目,我无权更改项目配置,因此必须保留原始链接顺序
然后我在package_b/c.cpp中添加了一个伪函数bar((,它什么都不做但只要调用foo((,原始的"g++ -o exec -Bstatic b.a a.a ..."
就会运行通过而没有任何链接错误
有人能告诉我为什么在在这种情况下,同样的程序包会起作用吗?
我使用的是g++4.4.4和linux 2.6.18-194.el5
如有任何意见,我们将不胜感激。
这是正常的。链接时,链接器会遍历对象文件列表,找到未定义的引用,然后由之后的其他对象文件/库来满足这些引用。
你可以通过改变这种行为
-
包括两次档案中的一次,如
g++ -o exec a.a b.a a.a
-
使用
-(
构建g++ -o exec -( a.a b.a -)
但请理解这是一个大项目,我无权更改项目配置,因此必须保留原始链接顺序。
运气不好。。。也许经理或其他人只是不希望您使用a
中b
中的函数。
然后我在package_b/c.cpp中添加了一个伪函数bar((,它只调用foo((,然后原始的"g++-o exec-Bstatic b.a a.a…"将在没有任何链接错误的情况下运行。
可能是package_b/c.cpp
的另一个函数已经被引用,链接器带走了bar()
(因为它们在同一个文件中(,而这个函数引用了foo()
,随后也包含在输出中。它成功了,因为foo
也在b.a
中。
您可能想了解链接器的工作原理。BTW,-Bstatic
标志是不必要的,因为.a.
对象文件档案仅静态链接(就好像在命令行上指定了.a
中包含的对象文件列表而不是.a
(。
或者,您可以始终使用--start-group
/--end-group
选项包装要链接的存档列表,使链接器多次扫描存档列表,这样就不需要对存档进行排序(就像MS VC++所做的那样(:
g++ -o exec -Wl,--start-group a.a b.a -Wl,--end-group
参见man ld
:
-( archives -)
--start-group archives --end-group
The archives should be a list of archive files. They may be either
explicit file names, or -l options.
The specified archives are searched repeatedly until no new
undefined references are created. Normally, an archive is searched
only once in the order that it is specified on the command line.
If a symbol in that archive is needed to resolve an undefined
symbol referred to by an object in an archive that appears later on
the command line, the linker would not be able to resolve that
reference. By grouping the archives, they all be searched
repeatedly until all possible references are resolved.
Using this option has a significant performance cost. It is best
to use it only when there are unavoidable circular references
between two or more archives.
GCC与VisualC++链接器不同,它要求按顺序提供静态库,以便在使用引用之前定义它们。不要问我为什么,但你必须始终检查你是否列出了要与GCC按正确顺序链接的文件。
这里有一个深入的解释。
使用静态库中的函数时,必须首先在命令行中放置使用该函数的文件,然后放置定义该函数的库。否则,如果首先放置定义,gcc(或者更具体地说,ld(将丢弃"未使用"的函数。抱歉,gcc就是这样工作的。
- 在C++中初始化向量映射的最有效方法
- 将此布尔值传递给此函数的最有效方法是什么?
- 比较C++变量的最有效方法
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- 存储变量的更有效方法是什么?
- 确保套装新鲜度的有效方法
- 当映射包含字符串向量作为值时,从值中获取键的有效方法
- 映射唯一值和重复值的有效方法.可以访问键或值的位置
- 在C++事务之间存储大量字符数据的有效方法
- 在unordered_multimap中精确迭代一次每个键的有效方法
- 一种将 Dart 中的字节数据转换为 C++ 中的无符号字符*的有效方法?
- 检查两个向量是否并行的最有效方法
- 从浮点数中删除小数部分但保留类型的有效方法
- 传递非泛型函数的最有效方法是什么?
- 按升序打印矢量的所有元素直到它为空而没有重复项的最有效方法是什么?
- 创建字符串数组的有效方法
- 返回一个引用C++中另一个类对象的对象的有效方法
- C++去除前x个元素的有效方法,在不改变向量大小的情况下将第x+1个元素推到第一个
- 将一种数据类型的向量复制到同一数据类型的结构向量中的有效方法是什么
- 从std::map值中获取密钥的有效方法