Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 静态库链接两次_C++ - Fatal编程技术网

C++ 静态库链接两次

C++ 静态库链接两次,c++,C++,我有以下设置: 静态库 链接到(1)的动态库 链接到(1.)和(2.)的可执行文件 来自静态库的代码现在被复制并出现在动态库和可执行文件中 问题: 数据(全局变量、静态类成员)是否也重复,可执行文件和dll是否看到相同的数据 Linux和Windows之间有区别吗 你将如何解决这个问题 编辑: 谢谢你的回答,我现在可以准确地解释我的情况了 静态库没有导出/导入标志。 动态库已导出其自己的符号 窗口: 动态库具有静态库的文本+数据段的副本。 可执行程序无法知道动态库已链接到静态库,因为从外部可以看

我有以下设置:

  • 静态库
  • 链接到(1)的动态库
  • 链接到(1.)和(2.)的可执行文件
  • 来自静态库的代码现在被复制并出现在动态库和可执行文件中

    问题:

    数据(全局变量、静态类成员)是否也重复,可执行文件和dll是否看到相同的数据

    Linux和Windows之间有区别吗

    你将如何解决这个问题

    编辑:

    谢谢你的回答,我现在可以准确地解释我的情况了

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

    窗口:

    动态库具有静态库的文本+数据段的副本。 可执行程序无法知道动态库已链接到静态库,因为从外部可以看到非静态库符号

    Linux:

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

    这是不好的,因为您通常希望在linux和windows上有相同的行为

  • 共享符号(linux上的默认值)
    • 将静态库链接到共享库时,对静态库中的所有符号添加dll导出命令<代码>\uuuuu属性(dllexport))
    • 将静态库链接到可执行文件时添加dll导入命令<代码>属性(dllimport))
    • 代码和数据只驻留在共享库中,并且可以从外部链接
  • 冗余符号(windows上的默认值)
    • 您需要确保静态库的符号不包括在共享库的符号表中
    • gcc上的属性((可见性(“隐藏”))
    • 链接可执行文件时,静态库中的符号在任何地方都找不到,因此它们会再次被包含

    据我所知,它取决于操作系统(因为C++语言没有说明图书馆应该如何工作)。 在windows上,您将获得两倍的代码和数据,更糟糕的是,将获得两倍于该库中声明的全局变量(!)

    当静态链接程序中的标准库和使用该库的库时,当您获得两个默认分配器时,如果在库上调用
    new
    ,在另一个库上调用
    delete
    ,则会出现此问题,对象将在
    new
    端泄漏,堆可能在
    delete
    端损坏


    我不知道其他操作系统的详细信息,但我预计可能会出现类似的问题。这是一个糟糕的情况,因为有两个可执行文件(exe和dll),每个文件都有其代码实例和全局数据。它们是独立构建的,不能共享内存映射


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

    是的,数据是重复的。您可以使用动态库来解决它。@UmNyobe:已经有一个DLL;创建另一个没有任何帮助,因为它不会与第一个共享全局数据。库是预编译的还是作为源代码提供的?+1用于新建/删除技巧:我过去遇到过这种情况,并很快学会了避免使用异构构建。如果所有库调用都正常运行(也就是说,它们不观察或修改任何全局状态)可以使用静态链接,因为代码可能更高效/小(只包括您正在使用的符号),在所有其他情况下,我建议不要使用它。在Linux上,数据似乎没有被复制。@dari我刚刚测试了这个,如果您配置链接器,使其不从静态库导出符号(我可以用不太小的努力做到这一点)在linux和mac os中也会得到类似的效果。发现此类问题的一种方法是使用valgrind。它将报告一个“无效自由”,后跟分配变量的代码位置(例如全局),以及尝试释放它的两个代码位置。如果您查看这两个释放,它们很可能指向两个不同的库,这是同一代码存在两次并且运行不正确的原因。我是否理解您的答案正确:在dll中重新声明静态库中的所有变量和函数,以便不必链接到静态库。是的,这就是我的意思,希望链接器会同意。库的头将以三种版本存在:编译静态的标准、导出以构建dll和导入exe。