【问题标题】:Linker error - undefined reference -gcc链接器错误 - 未定义的引用 -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 enum{false, true}bool;
typedef enum {CREATE_NEW_LIST, DOUBLE_THE_LIST, HALF_THE_LIST}Op;

#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

标签: c gcc linker


【解决方案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。
    猜你喜欢
    • 2014-03-04
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    • 2013-04-04
    相关资源
    最近更新 更多