【发布时间】:2016-08-26 06:30:22
【问题描述】:
谁能解释一下两个 g++ 实例如何处理将以下代码编译到共享库的差异?
Foo.h
#ifndef Foo_h
#define Foo_h
void Foo();
#endif // Foo_h
Foo.cpp
#include "Foo.h"
#include <iostream>
void Foo()
{
std::cout << "Greetings from Foo()!" << std::endl;
}
Bar.h
#ifndef Bar_h
#define Bar_h
void Bar();
#endif // Bar_h
Bar.cpp
#include "Bar.h"
#include "Foo.h"
#include <iostream>
void Bar()
{
Foo();
std::cout << "Greetings from Bar()!" << std::endl;
}
在真正的 Linux 机器上:
>g++ --version
g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
>g++ -fpic -c Foo.cpp
>g++ -fpic -c Bar.cpp
>g++ -shared -o libFoo.so Foo.o
>g++ -shared -o libBar.so Bar.o
>
在 Cygwin 上:
>g++ --version
g++ (GCC) 5.4.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
>g++ -fpic -c Foo.cpp
>g++ -fpic -c Bar.cpp
>g++ -shared -o libFoo.so Foo.o
>g++ -shared -o libBar.so Bar.o
Bar.o:Bar.cpp:(.text+0x9): undefined reference to `Foo()'
Bar.o:Bar.cpp:(.text+0x9): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `Foo()'
collect2: error: ld returned 1 exit status
我真的没有足够的 *nix-savvy 知道如何在任一盒子上安装不同/匹配版本的 g++ 以查看这是否是问题的原因(在其中一个盒子上我不会有无论如何,这样做的特权)。
我一直认为目标文件以及扩展的库(无论是静态的还是共享的)都允许具有未解析的符号,并且只有在链接可执行文件时才需要解析所有符号。这个概念在几年的开发经验中也基本成立,所以我对 Cygwin 上产生的错误感到困惑。我很想知道这里发生了什么。谢谢。
更新
下面的回答者提供了以下可行的建议:g++ -shared -o libBar.so Bar.o libFoo.so
查看 libBar.so 的结果内容:
>nm --demangle libBar.so | grep Foo
00000004e4b791c4 I __imp__Z3Foov
00000004e4b7903c I _head_libFoo_so
00000004e4b71750 T Foo()
00000004e4b793ec I libFoo_so_iname
根据我的理解,这意味着 Foo() 二进制包含在 libBar.so 中,即 Foo() 的编译二进制内容存在于 libBar.so 中。
这与我根据真正的 Linux 机器上的行为在脑海中的画面有点不同。我认为每个.so 都是“独立”的二进制代码,就像.o 文件或仅由一个目标文件组成的.a 文件一样。
我想我难以理解的是 Cygwin(或 g++ 5.4)的行为是说 library 不能有未解析的符号 - 这感觉与很多以前的经验在我心中根深蒂固。我知道可执行文件不能有未解决的问题,但库应该能够有未解决的问题,对吧?毕竟,你不能执行一个库——它没有main()。我确定 static 库可能有未解决的问题,我认为共享库和静态库之间的区别在于它们的代码是否在链接时 添加 到可执行二进制文件中,或者是否他们的代码由可执行文件在运行时查找。
感谢社区可以在这里进一步明确。谢谢。
【问题讨论】:
-
在 Windows 上没有共享对象。有DLL。 Cugwin 尽最大努力隐藏差异,但它只能做这么多。默认情况下,DLL 不允许有未解析的符号。
-
谢谢。您的解释(或在我看来)与@MartinBonner 的解释相矛盾。我将尝试更深入地了解这一切。同时,如果您非常确定自己的立场,您能否将其发布为答案以及您认为相关的任何进一步解释/背景?
-
@n.m. - 啊!这就解释了!你应该发布一个答案。
标签: c++ linux linker cygwin shared-libraries