C: 链接器命令失败,退出代码为 1
C: linker command failed with exit code 1
我在编译代码时遇到问题。我没有收到任何错误消息。但是,我收到以下消息:
Undefined symbols for architecture x86_64:
"_lookup", referenced from:
_main in sixteen2-85c27c.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我以前从未遇到过这样的事情,我在网上找到的大部分信息都涉及 Objective-C,而不是普通的 C。我将不胜感激。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {
struct entry {
char word[15];
char definition[100];
};
const struct entry dictionary[100] =
{{"aardvark", "a burrowing African mammal"},
{"abyss", "a bottomless pit"},
{"acumen", "mentally sharp; keen"},
{"addle", "to become confused"},
{"aerie", "a high nest"},
{"affix", "to append; attach"},
{"agar", "a jelly made from seaweed"},
{"ahoy", "a nautical call of greeting"},
{"aigrette", "an ornamental cluster of feathers"},
{"ajar", "partially opened"}};
int entries = 10;
int entryNumber;
int lookup (const struct entry dictionary[], const char search[], const int entries);
if (argc != 2)
{
fprintf (stderr, "No word typed on the command line.\n");
return EXIT_FAILURE;
}
entryNumber = lookup (dictionary, argv[1], entries);
if (entryNumber != -1)
printf("%s\n", dictionary[entryNumber].definition);
else
printf("Sorry, %s is not in my dictionary.\n", argv[1]);
return EXIT_SUCCESS;
}
您有以下代码行:
int lookup (const struct entry dictionary[], const char search[], const int entries);
在主函数里面。这有两个主要问题。
函数声明不能出现在另一个函数内部。我引用的行需要出现在你的主要功能之外,如下所示:
int lookup(.....)
//code here
int main(...)
{
//more code here
}
即使您声明函数“lookup”,您也从未定义它。这可能是导致 linker 错误的原因。编译器编译所有函数,然后 linker 一起去 link 函数(可以这么说)并发现,虽然函数“lookup”被声明然后稍后被调用,但它并没有真的存在于任何地方! (据我所知,stdlib.h 或 stdio.h 中不存在函数“lookup”)。这会阻止 linker 完成其工作。
概括地说,您的代码应该重组如下:
#include <stdio.h>
#include <stdlib.h>
int lookup (const struct entry dictionary[], const char search[], const int entries)
{
//lots of code belongs in here, but that's for you to figure out :)
}
int main (int argc, char *argv[]) {
struct entry {
char word[15];
char definition[100];
};
const struct entry dictionary[100] =
{{"aardvark", "a burrowing African mammal"},
{"abyss", "a bottomless pit"},
{"acumen", "mentally sharp; keen"},
{"addle", "to become confused"},
{"aerie", "a high nest"},
{"affix", "to append; attach"},
{"agar", "a jelly made from seaweed"},
{"ahoy", "a nautical call of greeting"},
{"aigrette", "an ornamental cluster of feathers"},
{"ajar", "partially opened"}};
int entries = 10;
int entryNumber;
//**REMOVE THIS LINE** Move it up top....
//int lookup (const struct entry dictionary[], const char search[], const int entries);
if (argc != 2)
{
fprintf (stderr, "No word typed on the command line.\n");
return EXIT_FAILURE;
}
entryNumber = lookup (dictionary, argv[1], entries);
if (entryNumber != -1)
printf("%s\n", dictionary[entryNumber].definition);
else
printf("Sorry, %s is not in my dictionary.\n", argv[1]);
return EXIT_SUCCESS;
}
希望对您有所帮助。如果您不明白“linker”的作用或为什么这很重要,请发表评论,我会相应地编辑我的答案。了解 linker 和编译器是区分平庸的 C 程序员和优秀的 C 程序员的众多因素之一!
我认为此时解释什么是 linker 会很有用。不过,在开始之前,了解您的编译器的作用以及编译程序的真正含义很重要。
根据您在问题中发布的代码,我认为可以安全地假设您不止一次使用过编译器 :)。我要说一些你已经知道的事情,但请坚持我的看法。您拥有的“.c”和“.h”文件描述了算法。这些文件很容易让人阅读和编辑,但是,您的计算机可能很难从中提取含义。为了让您的计算机“运行”这些文件中的程序,需要将算法转换为您的计算机可以理解的语言。这种被称为“机器语言”的语言是人类难以编写的,所以我们用C或C++编写,并通过编译器将我们的C和C++程序转换为“机器语言”。
现在,linker 的功能很微妙,但非常重要。初学者很容易认为 linker 完全没有必要:如果编译器将 C 转换为“机器语言”,那么工作就结束了,对吧?嗯...不完全是。
你看,你编译的程序中的每一点“机器语言”都有一个内存地址。考虑以下玩具示例:
#include <stdio.h>
int addnums(int numbers[], int length)
{
int total = 0;
for(int i = 0; i < length; i++)
{
total += numbers[i];
}
return total;
}
int main(int argc, char** argv)
{
int mynums[] = {1, 2, 3, 4, 5};
int total = addnums(mynums, 5);
printf("the total of the array is %i\n", total);
return 0;
}
如果我们查看这个玩具程序的机器代码,我们会发现每个函数在您的计算机内存中都有一个起点和一个终点。这意味着每个函数都有一个 address 开始的地方。当您的计算机执行行
int total = addnums(mynums, 5);
它需要“跳转”到机器代码的不同部分。 “int main()”可能从地址 100 开始,“int addnums()”在地址 50。您的计算机在到达此行时需要在地址 50 执行机器代码。
编译器不关心函数的地址。它只是编译代码,并将其留给另一个程序将正确的地址放入机器代码中。如果 linker 说
symbol(s) not found
表示linker不知道某个函数的地址。这通常是因为相关函数从未声明或定义过。如果 linker 要从此代码生成可执行文件,您的计算机将到达行
int total = addnums(mynums, 5);
然后说“嗯???我要去哪里??”如果“int addnums()”函数没有跳转到的地址,您的 cpu 将完全丢失。
你的程序会莫名其妙地崩溃。
linker 通过删除错误并停止编译过程来避免这种心痛。在我业余编写嵌入式系统的日子里,我遇到过几次这个问题,调试起来简直是一场噩梦。
希望这对您有所帮助。如果我的解释不好,请告诉我。
我在编译代码时遇到问题。我没有收到任何错误消息。但是,我收到以下消息:
Undefined symbols for architecture x86_64:
"_lookup", referenced from:
_main in sixteen2-85c27c.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我以前从未遇到过这样的事情,我在网上找到的大部分信息都涉及 Objective-C,而不是普通的 C。我将不胜感激。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {
struct entry {
char word[15];
char definition[100];
};
const struct entry dictionary[100] =
{{"aardvark", "a burrowing African mammal"},
{"abyss", "a bottomless pit"},
{"acumen", "mentally sharp; keen"},
{"addle", "to become confused"},
{"aerie", "a high nest"},
{"affix", "to append; attach"},
{"agar", "a jelly made from seaweed"},
{"ahoy", "a nautical call of greeting"},
{"aigrette", "an ornamental cluster of feathers"},
{"ajar", "partially opened"}};
int entries = 10;
int entryNumber;
int lookup (const struct entry dictionary[], const char search[], const int entries);
if (argc != 2)
{
fprintf (stderr, "No word typed on the command line.\n");
return EXIT_FAILURE;
}
entryNumber = lookup (dictionary, argv[1], entries);
if (entryNumber != -1)
printf("%s\n", dictionary[entryNumber].definition);
else
printf("Sorry, %s is not in my dictionary.\n", argv[1]);
return EXIT_SUCCESS;
}
您有以下代码行:
int lookup (const struct entry dictionary[], const char search[], const int entries);
在主函数里面。这有两个主要问题。
函数声明不能出现在另一个函数内部。我引用的行需要出现在你的主要功能之外,如下所示:
int lookup(.....) //code here int main(...) { //more code here }
即使您声明函数“lookup”,您也从未定义它。这可能是导致 linker 错误的原因。编译器编译所有函数,然后 linker 一起去 link 函数(可以这么说)并发现,虽然函数“lookup”被声明然后稍后被调用,但它并没有真的存在于任何地方! (据我所知,stdlib.h 或 stdio.h 中不存在函数“lookup”)。这会阻止 linker 完成其工作。
概括地说,您的代码应该重组如下:
#include <stdio.h>
#include <stdlib.h>
int lookup (const struct entry dictionary[], const char search[], const int entries)
{
//lots of code belongs in here, but that's for you to figure out :)
}
int main (int argc, char *argv[]) {
struct entry {
char word[15];
char definition[100];
};
const struct entry dictionary[100] =
{{"aardvark", "a burrowing African mammal"},
{"abyss", "a bottomless pit"},
{"acumen", "mentally sharp; keen"},
{"addle", "to become confused"},
{"aerie", "a high nest"},
{"affix", "to append; attach"},
{"agar", "a jelly made from seaweed"},
{"ahoy", "a nautical call of greeting"},
{"aigrette", "an ornamental cluster of feathers"},
{"ajar", "partially opened"}};
int entries = 10;
int entryNumber;
//**REMOVE THIS LINE** Move it up top....
//int lookup (const struct entry dictionary[], const char search[], const int entries);
if (argc != 2)
{
fprintf (stderr, "No word typed on the command line.\n");
return EXIT_FAILURE;
}
entryNumber = lookup (dictionary, argv[1], entries);
if (entryNumber != -1)
printf("%s\n", dictionary[entryNumber].definition);
else
printf("Sorry, %s is not in my dictionary.\n", argv[1]);
return EXIT_SUCCESS;
}
希望对您有所帮助。如果您不明白“linker”的作用或为什么这很重要,请发表评论,我会相应地编辑我的答案。了解 linker 和编译器是区分平庸的 C 程序员和优秀的 C 程序员的众多因素之一!
我认为此时解释什么是 linker 会很有用。不过,在开始之前,了解您的编译器的作用以及编译程序的真正含义很重要。
根据您在问题中发布的代码,我认为可以安全地假设您不止一次使用过编译器 :)。我要说一些你已经知道的事情,但请坚持我的看法。您拥有的“.c”和“.h”文件描述了算法。这些文件很容易让人阅读和编辑,但是,您的计算机可能很难从中提取含义。为了让您的计算机“运行”这些文件中的程序,需要将算法转换为您的计算机可以理解的语言。这种被称为“机器语言”的语言是人类难以编写的,所以我们用C或C++编写,并通过编译器将我们的C和C++程序转换为“机器语言”。
现在,linker 的功能很微妙,但非常重要。初学者很容易认为 linker 完全没有必要:如果编译器将 C 转换为“机器语言”,那么工作就结束了,对吧?嗯...不完全是。
你看,你编译的程序中的每一点“机器语言”都有一个内存地址。考虑以下玩具示例:
#include <stdio.h>
int addnums(int numbers[], int length)
{
int total = 0;
for(int i = 0; i < length; i++)
{
total += numbers[i];
}
return total;
}
int main(int argc, char** argv)
{
int mynums[] = {1, 2, 3, 4, 5};
int total = addnums(mynums, 5);
printf("the total of the array is %i\n", total);
return 0;
}
如果我们查看这个玩具程序的机器代码,我们会发现每个函数在您的计算机内存中都有一个起点和一个终点。这意味着每个函数都有一个 address 开始的地方。当您的计算机执行行
int total = addnums(mynums, 5);
它需要“跳转”到机器代码的不同部分。 “int main()”可能从地址 100 开始,“int addnums()”在地址 50。您的计算机在到达此行时需要在地址 50 执行机器代码。
编译器不关心函数的地址。它只是编译代码,并将其留给另一个程序将正确的地址放入机器代码中。如果 linker 说
symbol(s) not found
表示linker不知道某个函数的地址。这通常是因为相关函数从未声明或定义过。如果 linker 要从此代码生成可执行文件,您的计算机将到达行
int total = addnums(mynums, 5);
然后说“嗯???我要去哪里??”如果“int addnums()”函数没有跳转到的地址,您的 cpu 将完全丢失。
你的程序会莫名其妙地崩溃。
linker 通过删除错误并停止编译过程来避免这种心痛。在我业余编写嵌入式系统的日子里,我遇到过几次这个问题,调试起来简直是一场噩梦。
希望这对您有所帮助。如果我的解释不好,请告诉我。