我做了一个实验,看看如果我试着获得相同的函数在那里编译两次,会产生什么样的汇编语言。我做了以下内容:C链接器和重复符号
我创建了两个简单的测试文件及其相应的标题。我们称它们为a.c/a.h和b.c/b.h。以下是这些文件的内容:
A.H:
#ifndef __A_H__
#define __A_H__
int a(void);
#endif
b.h:
#ifndef __B_H__
#define __B_H__
int b(void);
#endif
交流转换器:
#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,包括了这段时间的静态档案:
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中调用,而不是内联的,然而,这只是有一个在代码中定义一个,没有重复。
看来GCC有两种:
- 检测到的复制对象的代码和除去的B归档首次使用的重复 - 或 -
- ,并且它包括为int一个基准(),所以一个存档被忽略。
我的问题是:这种行为是否符合我的测试要求?还是标准的,我能期待其他编译器的行为吗?显然重复代码是一个问题,但是也可能有重复的全局引用。构建一个具有多个依赖路径到相同静态存档的大型应用程序是否安全/良好实践?是否存在不太明显的情况,而不仅仅是重复的符号名称,在执行此操作时会出现问题
问这是因为我一直在玩这个想法,我正在做一个项目,并且想要做出正确的选择。
[如何处理C中重复的函数名?]可能的重复(http://stackoverflow.com/questions/3098380/how-to-deal-with-duplicated-function-name-within-c) – KevinDTimm
目前你的'bc'没有看到'a()'的声明。在'b.c'中缺少'#include“a.h”'? – jweyrich
建议删除C++标记 – chux