链接器错误 - 未定义的引用 -gcc
Posted
技术标签:
【中文标题】链接器错误 - 未定义的引用 -gcc【英文标题】:Linker error - undefined reference -gcc 【发布时间】:2016-12-20 21:57:00 【问题描述】:运行后,
Cygwin-PC ~/code_practice/Computing/list
$ gcc -c arrayImpl.c -o arrayImpl.o
代码目录结构,windows(cygwin)
Cygwin-PC ~/code_practice/Computing/stack
$ ls
main.c stack.h stackImpl.c
Cygwin-PC ~/code_practice/Computing/list
$ ls
arrayImpl.c arrayImpl.o linkedListImpl.c list.h main.c
Stack
抽象依赖于List
抽象,用于数据表示和使用。
List
抽象如下图,
/************ list.h ************/
/***************** Usage-start ************/
typedef enumfalse, truebool;
typedef enum CREATE_NEW_LIST, DOUBLE_THE_LIST, HALF_THE_LISTOp;
#if defined(ARRAY)
/* To ensure Encapsulation(i.e., maintain invariants of array) */
typedef struct List List;
#elif defined(LINKED_LIST)
/* To ensure Encapsulation(i.e., maintain invariants of linked list) */
/* User will not get access to node*/
typedef struct List List;
#else
#error "Wrong list implementation macro name !!!"
#endif
void insertItem(List *, void *newItem);
void *deleteItem(List *, int listIndex);
void *deleteLastItem(List *);
List* createList(List *, Op opType);
/***************** Usage-end ***************/
/***************** arrayImple.c **************/
#if defined(ARRAY)
#include"list.h"
/************ Representation - start ************/
typedef struct List
void **array;
/* Following members for Housekeeping - Array enhancement*/
int lastItemPosition;
int size;
List;
#define INITIAL_LIST_SIZE 50
/********************* Representation - end ************/
/************* Usage - start ***************/
List *createList(List *list, Op opType)
....
void insertItem(List *arrayList, void *newItem)
...
void *deleteItem(List *arrayList, int listIndex)
....
void * deleteLastItem(List *arrayList)
...
/******************** Usage - end *******************/
#endif
Stack
抽象,如下图,
/********* stack.h *********/
#include"../list/list.h"
typedef struct Stack Stack;
Stack *createStack();
void push(Stack *, void *item);
void*pop(Stack *);
/*********** stackImpl.c *******/
#include"../list/list.h"
typedef struct Stack
List *stack;
Stack;
Stack* createStack()
Stack *s = malloc(sizeof(Stack));
s->stack = createList((void *)0, CREATE_NEW_LIST);
return s;
void push(Stack *s, void *item)
insertItem(s->stack, item);
void *pop(Stack *s)
void *item = deleteLastItem(s->stack);
return item;
下面的编译说,下面给出的消息,不涉及链接器,
Cygwin-PC ~/code_practice/Computing/stack
$ gcc -c -DARRAY main.c stackImpl.c ../list/arrayImpl.o
gcc: warning: ../list/arrayImpl.o: linker input file unused because linking
not done
以下编译失败,出现以下错误,
Cygwin-PC ~/code_practice/Computing/stack
$ gcc -DARRAY main.c stackImpl.c ../list/arrayImpl.o
/tmp/ccapgYQI.o:stackImpl.c:(.text+0x25): undefined reference to
`createList'
/tmp/ccapgYQI.o:stackImpl.c:(.text+0x4b): undefined reference to
`insertItem'
/tmp/ccapgYQI.o:stackImpl.c:(.text+0x61): undefined reference to
`deleteLastItem'
collect2: error: ld returned 1 exit status
问题,
从上面的编译命令,为什么 GNU 链接器(ld
)不接受../list/arrayImpl.o
文件来查找createList()
、insertItem()
和deleteLastItem()
的定义
以下编译作品,
Cygwin-PC ~/code_practice/Computing/stack
$ gcc -DARRAY main.c stackImpl.c ../list/arrayImpl.c
【问题讨论】:
因为gcc -c
只编译而不链接。给它*.o
文件是没有用的,因为警告是友好的建议。
-c
表示仅编译(不要链接)。因此无法提供.o
文件,因为它无法编译(它已经编译,需要链接)。
另请注意,来自 C99 的 <stdbool.h>
提供了 bool
、true
、false
,因此您不需要定义 typedef enum false, true bool;
,尽管它没有太大的危害。 stack.h
中包含的四个标头中没有一个实际上是 stack.h
需要的;您不应该将您的标题与不必要的其他标题混淆。需要Op
typedef; typedef struct List List;
应该是无条件的(抽象的消费者不需要关心您的列表类型是如何实现的;这纯粹是一个实现问题)。你应该从根本上简化你的标题。
大量无用代码,原因是命令行不完整。
文件:stackimpl.c
似乎缺少声明:#include "stack.h"
强烈建议 *.c 文件的头文件与 *.c 文件同名,唯一的区别是扩展名是.h
而不是.c
【参考方案1】:
gcc -c arrayImpl.c -o arrayImpl.o
缺少-DARRAY
。如果没有,arrayImpl.c
中的代码将被有条件地删除:
/***************** arrayImple.c **************/
#if defined(ARRAY)
【讨论】:
【参考方案2】:这个
Cygwin-PC ~/code_practice/Computing/stack
$ gcc -DARRAY main.c stackImpl.c ../list/arrayImpl.o
/tmp/ccapgYQI.o:stackImpl.c:(.text+0x25): undefined reference to
`createList'
/tmp/ccapgYQI.o:stackImpl.c:(.text+0x4b): undefined reference to
因为你错过了arrayImpl.c而失败
kaylum 有正确的答案,当你编译 arrayImpl.c 时你忘记了 -DARRAY
【讨论】:
但是链接器接受arrayImpl.o
文件进行链接吗?
好像不行,为什么不直接放arrayImpl.c
过去我确实使用链接器将main.c
与多个.o
文件链接。如果gcc
在预处理(cpp
)、编译(cc
)&组装(as
)之后实际运行ld
,gcc
是否带.o
或.c
链接?这就是为什么我给了../list/arrayImpl.o
@overexchange 一次编译多个源代码文件是很不寻常的,如果你用传统的方式编译stackImpl.c,然后再编译gcc -DARRAY main.c stackImpl.o ../list/arrayImpl.o
就可以了。
请将该信息添加到问题中。这是错误的,是问题的原因。缺少-DARRAY
。以上是关于链接器错误 - 未定义的引用 -gcc的主要内容,如果未能解决你的问题,请参考以下文章