链接时未定义的引用错误
编译中最常见的错误之一发生在链接阶段。该错误看起来类似于:
$ gcc undefined_reference.c
/tmp/ccoXhwF0.o: In function `main':
undefined_reference.c:(.text+0x15): undefined reference to `foo'
collect2: error: ld returned 1 exit status
$
那么让我们看一下生成此错误的代码:
int foo(void);
int main(int argc, char **argv)
{
int foo_val;
foo_val = foo();
return foo_val;
}
我们在这里看到 foo(int foo();
) 的声明,但没有它的定义 (实际函数)。所以我们为编译器提供了函数头,但是在任何地方都没有定义这样的函数,所以编译阶段通过但链接器以 Undefined reference
错误退出。
要在我们的小程序中修复此错误,我们只需要为 foo 添加一个定义 :
/* Declaration of foo */
int foo(void);
/* Definition of foo */
int foo(void)
{
return 5;
}
int main(int argc, char **argv)
{
int foo_val;
foo_val = foo();
return foo_val;
}
现在这段代码将编译。另一种情况出现在 foo()
的源位于一个单独的源文件 foo.c
中(并且有一个头文件 foo.h
来声明 foo()
包含在 foo.c
和 undefined_reference.c
中)。然后修复是链接 foo.c
和 undefined_reference.c
的目标文件,或者编译两个源文件:
$ gcc -c undefined_reference.c
$ gcc -c foo.c
$ gcc -o working_program undefined_reference.o foo.o
$
要么:
$ gcc -o working_program undefined_reference.c foo.c
$
更复杂的情况是涉及到库,例如代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char **argv)
{
double first;
double second;
double power;
if (argc != 3)
{
fprintf(stderr, "Usage: %s <denom> <nom>\n", argv[0]);
return EXIT_FAILURE;
}
/* Translate user input to numbers, extra error checking
* should be done here. */
first = strtod(argv[1], NULL);
second = strtod(argv[2], NULL);
/* Use function pow() from libm - this will cause a linkage
* error unless this code is compiled against libm! */
power = pow(first, second);
printf("%f to the power of %f = %f\n", first, second, power);
return EXIT_SUCCESS;
}
代码在语法上是正确的,pow()
的声明存在于 #include <math.h>
,所以我们尝试编译和链接但是得到如下错误:
$ gcc no_library_in_link.c -o no_library_in_link
/tmp/ccduQQqA.o: In function `main':
no_library_in_link.c:(.text+0x8b): undefined reference to `pow'
collect2: error: ld returned 1 exit status
$
这是因为在链接阶段没有找到 pow()
的定义。要解决这个问题,我们必须通过指定 -lm
标志来指定我们想要链接到名为 libm
的数学库。 (请注意,有些平台,如 macOS,不需要 -lm
,但是当你得到未定义的引用时,需要库。)
所以我们再次运行编译阶段,这次指定库(在源文件或目标文件之后):
$ gcc no_library_in_link.c -lm -o library_in_link_cmd
$ ./library_in_link_cmd 2 4
2.000000 to the power of 4.000000 = 16.000000
$
它的工作原理!