C++ C++;,链接顺序是否标准化?

C++ C++;,链接顺序是否标准化?,c++,linker,numerics,C++,Linker,Numerics,在我的linux设备上,我有两个库: libfoo1.a and libfoo2.a 它们都包含一个 void foo(int) 我的主要程序叫做foo: int main() { foo(1); return 0; } 我用两种方法编译了这个程序++ g++ main.cpp libfoo1.a libfoo2.a -o a1.out g++ main.cpp libfoo2.a libfoo1.a -o a2.out 当我运行程序时,a1显然在使用libfoo1.a中的foo()实现

在我的linux设备上,我有两个库:

libfoo1.a and libfoo2.a
它们都包含一个

void foo(int)
我的主要程序叫做foo:

int main() { foo(1); return 0; }
我用两种方法编译了这个程序++

g++ main.cpp libfoo1.a libfoo2.a -o a1.out
g++ main.cpp libfoo2.a libfoo1.a -o a2.out
当我运行程序时,a1显然在使用libfoo1.a中的foo()实现,而a2显然在使用libfoo2。也就是说,g++链接了它最先看到的foo()

我的问题(最后)是,这个“贪婪”链接策略是否在C++标准中实际指定?或者不同的编译器/平台是否会以实现定义的方式表现出不同的行为

PS:把这个问题放到实际环境中,我真的很喜欢这个g++示例的工作方式。在我的实际应用程序中,我有一个遗留的libfoo2,它实现了很多(很多!)函数,但我想在libfoo1中为其中一些函数提供新的实现。一方面,我可以在libfoo1中编写一个全新的接口,实现我的少数接口,然后将剩余的接口委托给libfoo2。但如果我可以依靠linker来为我编写委托代码(即使是像icc这样的非g++编译器),我宁愿避免编写所有委托代码

PPS:在实际环境中,libfoo2是blas,libfoo1是其一些例程的自制OpenMP实现。我还没准备好为MKL买单。ATLAS不会对我要调用的函数进行多线程处理。它非常擅长于多线程GEMM,但我需要LAPACK中的一些更古怪的例程来加快速度(zsptrf/zsptrs/zspr)。这些例程的my cache-Unknown OpenMP实现似乎比其缓存调优的顺序实现做得更好


很抱歉,文章太长。

标准中没有任何关于链接顺序的内容。我想说的是,依赖编译器使用的任何顺序都不是一种好的做法。

标准没有提到任何链接顺序。我要说的是,依赖编译器使用的任何顺序都不是一种好的做法。

几乎所有链接器都会按照您所描述的那样运行

链接器的传统行为是在命令行上指定的库中从左到右搜索外部函数。这意味着包含函数定义的库应该出现在使用它的任何源文件或目标文件之后


从。

几乎所有链接器都将按照您所描述的方式运行

链接器的传统行为是在命令行上指定的库中从左到右搜索外部函数。这意味着包含函数定义的库应该出现在使用它的任何源文件或目标文件之后


从.< /P> < P>从我可以看出,C++标准不涉及链接器。这就是为什么,例如,明文32和微软的C++编译器可以使用不同的名字篡改方案。<>(p>)从我可以看出,C++标准不涉及链接器。这就是为什么,例如,明文32和微软的C++编译器可以使用不同的名称篡改方案。

< P>根据标准,您有两个相同函数的定义,违反了一个定义规则。结果是未定义的行为


处理这个问题的“正确”方法可能是获取原始存档并从中提取所有对象文件。然后将新的对象文件复制到目录中,并创建一个只包含所需对象文件版本的新库。最后,与您的组合库链接(希望原始库中的任何内容都不依赖于您所替换的任何函数的未记录内容)。

根据标准,同一函数有两个定义,这违反了“一个定义”规则。结果是未定义的行为


处理这个问题的“正确”方法可能是获取原始存档并从中提取所有对象文件。然后将新的对象文件复制到目录中,并创建一个只包含所需对象文件版本的新库。最后,链接到您的组合库(希望原始库中的任何内容都不依赖于您所替换的任何函数的未记录内容)。

关于名称损坏的观点非常好!我明白这意味着链接无法标准化。值得一提的是,讨论中的foo库将使用extern“C”链接。这是否使我的问题变得更容易或改变了答案?名称损坏和名称解析顺序这两个概念没有很强的相关性。鼓励实现使用不同的损坏技术,以避免将具有不同异常和vtable语义的对象链接在一起。不过,这些都应该隐藏在构建系统之外,并且具有一致的链接器行为可以更容易地将一个工具链完全替换为另一个工具链。关于名称混乱的观点非常好!我明白这意味着链接无法标准化。值得一提的是,讨论中的foo库将使用extern“C”链接。这是否使我的问题变得更容易或改变了答案?名称损坏和名称解析顺序这两个概念没有很强的相关性。鼓励实现使用不同的损坏技术,以避免将具有不同异常和vtable语义的对象链接在一起。但是,这些都应该隐藏在构建系统中,并且具有一致的链接器行为可以更容易地将一个工具链完全替换为另一个工具链。作为后续,我是否至少可以保证链接器在不同库中看到foo()的两个定义时不会崩溃?如果是这样的话,我不介意只发送用户两个.a,让他们摆弄他们的链接器(或库归档器)来运行应用程序。@RAC我认为没有链接器会崩溃;但是,如果有多个定义,一些链接器将无法链接。作为后续,我是否至少可以保证链接器不会崩溃