2014-12-22 32 views
-3

我被困在這個編譯錯誤,我不知道如何調試代碼。我的程序主要有以下文件:如何刪除我的代碼中未定義的引用?

的Makefile:

CFLAGS = -Wall -g 
src = ex19.c 

all: $(src) 
    cc $(CFLAGS) -o ex19 $(src) 

ex19: object.o 

clean: 
    rm -f ex19 

object.h:

#ifndef _object_h 
#define _object_h 

typedef enum{ 
    NORTH, SOUTH, EAST, WEST 
} Direction; 

typedef struct { 
    char *description; 
    int (*init)(void *self); 
    void (*describe)(void *self); 
    void (*destroy)(void *self); 
    void *(*move)(void *self, Direction direction); 
    int (*attack)(void *self, int damage); 
} Object; 

int Object_init(void *self); 
void Object_destroy(void *self); 
void Object_describe(void *self); 
void *Object_move(void *self, Direction direction); 
int Object_attack(void *self, int damage); 
void *Object_new(size_t size, Object proto, char *description); 

#define NEW(T, N) Object_new(sizeof(T), T##Proto, N) 
#define _(N) proto.N 

#endif 

object.c:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include "object.h" 
#include <assert.h> 

void Object_destroy(void *self) { 
    Object *obj = self; 

    if(obj) { 
     if(obj->description) free(obj->decription); 
     free(obj); 
    } 
} 

void Object_describe(void *self) { 
    Object *obj = self; 
    printf("%s.\n", obj->description); 
} 

int Object_init(void *self){ 
    // do nothing really 
    return 1; 
} 

void *Object_move(void *sefl, Direction direction){ 
    printf("You can't go that direction.\n"); 
    return NULL; 
} 

int Object_attack(void *self, int damage){ 
    printf("You can't attack that.\n"); 
    return 0; 
} 

void *Object_new(size_t size, Object proto, char *description){ 
    // setup the default functions in case they aren't set 
    if(!proto.init) proto.init = Object_init; 
    if(!proto.describe) proto.describe = Object_describe; 
    if(!proto.destroy) proto.destroy = Object_destroy; 
    if(!proto.attack) proto.attack = Object_attack; 
    if(!proto.move) proto.move = Object_move; 

    // this seems weird, but we can make a struct of one size, 
    // then point a different pointer at it to "cast" it 
    Object *el = calloc(1, size); 
    *el = proto; 

    // copy the description over 
    el->description = strdup(description); 

    // initialize it with whatever init we were given 
    if(!el->init(el)){ 
     // looks like it didn't initialize properly 
     el->destroy(el); 
     return NULL; 
    } 
    else { 
     //all done, we made an object of any type 
     return el; 
    } 
} 

ex19.h:

#ifndef __ex19_h 
#define __ex19_h 

#include "object.h" 

struct Monster { 
    Object proto; 
    int hit_points; 
}; 

typedef struct Monster Monster; 

int Monster_attack(void *self, int damage); 
int Monster_init(void *self); 

struct Room{ 
    Object proto; 

    Monster *bad_guy; 

    struct Room *north; 
    struct Room *south; 
    struct Room *east; 
    struct Room *west; 
}; 

typedef struct Room Room; 

void *Room_move(void *self, Direction direction); 
int Room_attack(void *self, int damage); 
int Room_init(void *self); 

struct Map{ 
    Object proto; 
    Room *start; 
    Room *location; 
}; 

typedef struct Map Map; 

void *Map_move(void *self, Direction direction); 
int Map_attack(void *self, int damage); 
int Map_init(void *self); 

#endif 

ex19.c:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 
#include <time.h> 
#include "ex19.h" 

int Monster_attack(void *self, int damage){ 
    Monster *monster = self; 
    printf("You attack %s!\n", monster->_(description)); 
    monster->hit_points -= damage; 
    if(monster->hit_points > 0) { 
     printf("It is still alive.\n"); 
     return 0; 
    } 
    else{ 
     printf("It is dead!\n"); 
     return 1; 
    } 
} 

int Monster_init(void *self){ 
    Monster *monster = self; 
    monster->hit_points = 10; 
    return 1; 
} 

Object MonsterProto = { 
    .init = Monster_init, 
    .attack = Monster_attack 
}; 

void *Room_move(void *self, Direction direction) { 
    Room *room = self; 
    Room *next = NULL; 

    if(direction == NORTH && room->north) { 
     printf("You go north, into:\n"); 
     next = room->north; 
    } 
    else if(direction == SOUTH && room->south){ 
     printf("You go south, into:\n"); 
     next = room->south; 
    } 
    else if(direction == EAST && room->east){ 
     printf("You go east, into:\n"); 
     next = room->east; 
    } 
    else if(direction == WEST && room->west){ 
     printf("You go west, into:\n"); 
     next = room->west; 
    } 
    else { 
     printf("You can't go that direction."); 
     next = NULL; 
    } 

    if(next){ 
     next->_(describe)(next); 
    } 
    return next; 
} 

int Room_attack(void *self, int damage){ 
    Room *room = self; 
    Monster *monster = room->bad_guy; 

    if(monster){ 
     monster->_(attack)(monster, damage); 
     return 1; 
    } 
    else{ 
     printf("You flail in the air at nothing. Idiot.\n"); 
     return 0; 
    } 
} 

Object RoomProto = { 
    .move = Room_move, 
    .attack = Room_attack 
}; 

void *Map_move(void *self, Direction direction){ 
    Map *map = self; 
    Room *location = map->location; 
    Room *next = NULL; 

    next = location->_(move)(location, direction); 
    if(next) { 
     map->location = next; 
    } 
    return next; 
} 

int Map_attack(void *self, int damage){ 
    Map* map = self; 
    Room *location = map->location; 
    return location->_(attack)(location, damage); 
} 

int Map_init(void *self){ 
    Map *map = self; 

    //make some rooms for a small map 
    Room *hall = NEW(Room, "The great hall"); 
    Room *throne = NEW(Room, "The throne room"); 
    Room *arena = NEW(Room, "The arena, with the minotaur"); 
    Room *kitchen = NEW(Room, "Kitchen, you have the knife now"); 

    // put the bad guy in the arena 
    arena->bad_guy = NEW(Monster, "The evil minotaur"); 

    // setup the map rooms 
    hall->north = throne; 

    throne->west = arena; 
    throne->east = kitchen; 
    throne->south = hall; 

    arena->east = throne; 
    kitchen->west = throne; 

    //start the map and the character off in the hall 
    map->start = hall; 
    map->location = hall; 

    return 1; 
} 

Object MapProto = { 
    .init = Map_init, 
    .move = Map_move, 
    .attack = Map_attack 
}; 

int process_input(Map *game){ 
    printf("\n> "); 
    char ch = getchar(); 
    getchar(); // eat enter; 

    int damage = rand() % 4; 
    switch(ch){ 
     case -1: 
      printf("Giving up? You such.\n"); 
      return 0; 
      break; 
     case 'n': 
      game->_(move)(game, NORTH); 
      break; 
     case 's': 
      game->_(move)(game, SOUTH); 
      break; 
     case 'e': 
      game->_(move)(game, EAST); 
      break; 
     case 'w': 
      game->_(move)(game, WEST); 
      break; 
     case 'a': 
      game->_(attack)(game, damage); 
      break; 
     case 'l': 
      printf("You can go:\n"); 
      if(game->location->north) printf("NORTH\n"); 
      if(game->location->south) printf("SOUTH\n"); 
      if(game->location->east) printf("EAST\n"); 
      if(game->location->west) printf("WEST\n"); 
      break; 
     default: 
      printf("What?: %d\n", ch); 
    } 
    return 1; 
} 

int main(int argc, char *argv[]){ 
    //simple way to setup the randomness 
    srand(time(NULL)); 

    //make our map to work with 
    Map *game = NEW(Map, "The hall of the Minotaur."); 
    printf("You enter the "); 
    game->location->_(describe)(game->location); 
    while(process_input(game)) { 
    } 
    return 0; 
} 

編譯錯誤:

立方厘米-Wall -g -o EX19 ex19.c /tmp/cccuR81O.o:在功能Map_init': ex19/ex19.c:105: undefined reference to Object_new」 EX19/EX19 .C:106:未定義參照Object_new' ex19/ex19.c:107: undefined reference to Object_new ' EX19/ex19.c:108:未定義參照Object_new' ex19/ex19.c:111: undefined reference to Object_new' EX19/ex19.c:180:爲`Object_new」更未定義的引用遵循 collect2:錯誤:LD返回1退出狀態 make:*** [全部]錯誤1

更新1:有問題的

105 Room *hall = NEW(Room, "The great hall"); 
106 Room *throne = NEW(Room, "The throne room"); 
107 Room *arena = NEW(Room, "The arena, with the minotaur"); 
108 Room *kitchen = NEW(Room, "Kitchen, you have the knife now"); 

111 arena->bad_guy = NEW(Monster, "The evil minotaur"); 
+0

你知道這裏的代碼轉儲沒有行號嗎? –

+0

對不起,我更新了行號。 – drdot

回答

2

生成文件需要被更新,以object.o鏈接到可執行行。目前您的鏈接線:

cc $(CFLAGS) -o ex19 $(src) 

如果執行make(或make all),那麼該命令將擴展爲:

cc -Wall -g -o ex19 ex19.c 

它試圖只用ex19.c來生成可執行文件。

構建目標ex19永遠不會被調用,因爲all沒有它作爲一個依賴。但即使這樣做,或者您手動編寫make ex19,仍然只會生成object.o,但您沒有任何鏈接ex19.oobject.o的任何命令來生成可執行文件。

您應該將src = ex19.c更改爲src = ex19.c object.c,因爲這些都是源文件。您可以取出ex19: object.o行,因爲它在這裏是多餘的。這個makefile會編譯和鏈接所有源文件在一行中,這很好。

如果你想改變你的makefile使用編譯器對每個.c文件的單獨調用(因此需要連接器需要第三次調用),那麼你需要做一些修改,最好是模擬你的makefile關閉現有的。

+0

謝謝你的回答。這工作!你可以添加一個關於chaging makefile的例子來爲每個.c文件使用單獨的編譯器調用,然後使用鏈接器調用嗎?我有興趣瞭解這一點。 – drdot

+0

@dannycrane [see here](http://stackoverflow.com/a/2481307/1505939)舉一個例子。你可以自動化它,這樣你只需要提供'$(src)'和所有其他規則就可以轉換c文件列表,但是首先理解基本知識是很好的 –

相關問題