2015-07-03 213 views
2

我有以下设置:静态库链接两次

  1. 静态库
  2. 链接到链接到(1)(1)
  3. 的可执行文件和动态库( 2.)

来自静态库的代码现在被复制并存在于动态库和可执行文件中。

问题:

是数据(全局变量,静态类成员)也复制并执行可执行文件和DLL看到相同的数据?

Linux和Windows之间有区别吗?

你会如何解决这个问题?

编辑:

感谢您的答案,我无法解释我的情况下发生的事情完全一样。

静态库没有导出/导入标志。 动态库帽子导出自己的符号。

的Windows:

动态库有静态库的文本+数据segement的副本。 可执行程序无法知道动态库是否链接了静态库,因为静态库符号的非外部可见。

的Linux:

动态库有静态库的文本数据segement的副本。 虽然动态库包含静态库中的所有符号(文本和数据),但它们在其自己的符号表中。 - >可执行文件看到,动态库已经定义了静态库的所有符号,并且没有重新定义它们。

这很糟糕,因为您通常需要在Linux和Windows上使用相同的行为。

  1. 分享符号(在Linux默认)

    • 上所有的符号连接起来,共享库时,添加DLL导出命令,从静态库。 __attribute__ ((dllexport))
    • 将静态库链接到可执行文件时添加一个dll导入命令。__attribute__ ((dllimport))
    • 的代码和数据只存在于共享库,并从外面
  2. Reduntant符号可链接(在Windows默认)

    • 你需要确保的符号静态库不包含在共享库的符号表中
    • __attribute__ ((visibility ("hidden"))) on gcc
    • 当链接可执行文件时,来自静态li brary不能在任何地方找到,所以他们再次被包括在内。
+1

是的,数据是重复的。你可以通过使用动态库来解决它。 – UmNyobe

+0

@UmNyobe:已经有一个DLL;创造另一个将是没有帮助的,因为它不会与第一个共享全球数据。 –

+0

库是否预编译或可用作源代码? –

回答

4

据我所知,这取决于操作系统(因为C++语言没有说太多关于图书馆应该如何工作)。

在Windows上,你会得到两倍的代码和数据,而这更糟糕的所有两次全球在该库中声明的变量(!)

这个问题静态链接标准库中时显示出来一个程序和一个使用它的库,当你得到两个默认分配器时,如果你在库上调用new,而在另一个上调用delete,那么该对象将在new一侧泄漏,并且堆在delete一侧可能会损坏。

我不知道其他操作系统的细节,但我希望类似的问题可能会出现

+0

+1新增/删除技巧:我在过去遭受过这种情况,很快就学会了避免使用异构构建。 –

+0

如果所有库调用都是_functional_(即它们没有观察或修改任何全局状态),则可以使用静态链接,因为代码可能更有效/更小(仅包含您使用的符号),在所有其他情况下,我建议反对它 – pqnet

+0

似乎在Linux上以某种方式不复制数据。 http://stackoverflow.com/questions/4925233/global-variable-has-multiple-copies-on-windows-and-a-single-on-linux-when-compil – dari

0

IMO这是一个讨厌的情况,因为有两个可执行文件(exe文件和DLL),各自有各自的实例代码和全局数据。它们是独立构建的,无法共享其内存映射。

一个选项可以让dll公开静态库的必需成员,以便exe可以直接链接到它们。

+0

我理解你的答案是否正确:在dll中重新声明静态库中的所有变量和函数,以便可执行文件不必链接到静态库。 – dari

+0

是的,这就是我的意思,希望链接器会同意。该库的头文件将存在三个版本:编译静态的标准,导出为构建DLL和EXE导入。 –