gpt4 book ai didi

C 链接器和重复符号

转载 作者:行者123 更新时间:2023-11-30 16:58:25 26 4
gpt4 key购买 nike

我做了一个实验,看看如果我尝试在其中编译两次相同的函数,会生成什么样的汇编语言。我做了以下事情:

我创建了两个简单的测试文件及其相应的 header 。我们称它们为 a.c/a.h 和 b.c/b.h。以下是这些文件的内容:

啊:

#ifndef __A_H__
#define __A_H__

int a( void );

#endif

b.h:

#ifndef __B_H__
#define __B_H__

int b( void );

#endif

a.c:

#include "a.h"

int a( void )
{
return 1;
}

b.c:

#include "b.h"
#include "a.h"

int b( void )
{
return 1 + a();
}

然后我为以下内容创建了一个静态存档:

gcc -c a.c -o a.o
ar -rsc a.a a.o

b 也一样,包括这次 a 的静态存档:

gcc -c b.c -o b.o
ar -rsc b.a a.a b.o

此时,我反汇编了 b 的静态存档,以验证它是否具有函数 a() 和 b() 的汇编代码。确实如此。

现在,我定义最后一个文件:

main.c:

#include <stdio.h>

#include "a.h"
#include "b.h"

int main( void )
{
printf( "%d %d\n", a(), b() );

return 0;
}

我这样编译它:

gcc main.c a.a b.a -o main

这很好用。当我反汇编它时,我在代码中看到了以下 a 和 b 的定义:

140 0000000000400561 <a>:
141 400561: 55 push %rbp
142 400562: 48 89 e5 mov %rsp,%rbp
143 400565: b8 01 00 00 00 mov $0x1,%eax
144 40056a: 5d pop %rbp
145 40056b: c3 retq
146
147 000000000040056c <b>:
148 40056c: 55 push %rbp
149 40056d: 48 89 e5 mov %rsp,%rbp
150 400570: e8 ec ff ff ff callq 400561 <a>
151 400575: 83 c0 01 add $0x1,%eax
152 400578: 5d pop %rbp
153 400579: c3 retq
154 40057a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)

如您所见,代码中明确将 b 定义为调用 a 而不是内联它,但是代码中对 a 的定义只有一个,没有重复。

gcc 似乎有:

  1. 检测到重复的目标代码并删除重复项--或者--
  2. 首先使用了 b 存档,其中包含对 int a() 的引用,因此 a 存档被忽略。

我的问题是:这种行为是我的测试的环境条件还是标准,我可以期望其他编译器有相同的行为吗?显然,重复的代码是一个问题,但是也可能存在重复的全局引用。构建一个具有多个指向同一静态存档的依赖路径的大型应用程序是否安全/良好的做法?执行此操作时是否存在比重复符号名称更不明显的情况会出现问题?

问这个问题是因为我一直在为我正在进行的项目考虑这个想法,并希望做出正确的选择。

最佳答案

My question is: is this behavior circumstantial to my test or is it standard, and can I expect the same behavior from other compilers?

就编译器本身而言,没有问题:源代码中的每个函数都有一个定义。

ar 而言,您也没有问题:您构建的两个文件都不包含任何重复的符号。

但是,不同的链接器可能表现出不同的行为。可以想象,有些人会拒绝链接包含重复外部符号的文件。典型的 UNIX 链接器将处理您所遇到的情况,但它们可能在一些细节上有所不同,例如二进制文件中是否包含函数 a() 的重复副本。

Obviously duplicate code is one problem, however there could be duplicate global references as well. Is it safe/good practice to build a large application that has multiple dependency paths to the same static archive?

“同一静态存档的多个路径”似乎不能很好地描述您所呈现的情况。在这两种情况下,您都不会多次提供相同的存档。相反,在 b 情况下,您提供具有重复成员的不同文件。链接器通常不会在同一个链接命令中多次指定相同的存档时遇到问题。在某些情况下甚至可能有必要这样做;它不应该出现问题。

提供具有重复成员的不同存档可能不会出现问题,除非可能会因重复的函数实现而导致代码膨胀。这有点不太确定,但我怀疑这在实践中会出现问题。

这是否是好的做法是一个见仁见智的问题,但我倾向于认为不是。我也不清楚你在这种方法中看到了什么收获。另一方面,如果你决定继续前进,我不会磨任何木桩或准备任何引火物。

关于C 链接器和重复符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38860480/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com