2013-02-03 167 views
0

我有5個文件在一個目錄中。我試圖用gcc -o mini2.c -pthread -utils編譯了一個程序,我收到以下錯誤:未定義的引用memdup

/tmp/cc2W2ocr.o: In function `fifo_put': 
mini2.c:(.text+0x59): undefined reference to `memdup' 
collect2: ld returned 1 exit status 

任何想法如何,我可以使memdup功能的編譯器可見?我在目錄中的文件:

  • mini2.c

     // Mini Assignment 1 
         // Author: Georges Krinker 
         // Student #: 260369844 
         // Course: ECSE 427 (OS) 
    
    
         #include <stdio.h> 
         #include <stdlib.h> 
    
         extern char etext, edata,end; 
         int not_init; 
         int init =10; 
         int dat =20; 
    
         int main(void){ 
    
          char *stack = (char*)alloca(10000); 
          int pid; 
          char *dynamic_var = (char*)malloc(4000); 
          int c =0; 
          FILE *file; 
          char l[8000]; 
          int len=8000; 
          char s [1200]; 
    
          // To find where the stack is we use the start of the last declared local variable s. 
          // This is because of the LIFO nature of the stack 
          // For a more accurate look at proc/pid/smaps and see the stack range (Readme.html) 
    
    
          printf("The stack starts approx. at %p\n", &s[1200]); 
    
          printf("The stack ends at %p\n\n", stack-10000); 
    
          // The most reliable way to obtain the Memory mapping segment is to read 
          // the proc/pid/maps file. (see Readme.html) 
    
          printf("The entire memory mapping segment spans:\n"); 
    
          sprintf(s, "/proc/%d/maps", pid=getpid()); 
    
          file = fopen(s, "r"); 
          if (file) { 
           //skip first 4 lines of the maps file 
           fgets(l, len, file); 
           fgets(l, len, file); 
           fgets(l, len, file); 
           fgets(l, len, file); 
           fgets(l, len, file); 
           while (c <= 9) { 
            fgets(l, len, file); 
            fputs (l, stdout); /*print the memeory mapping segments */ 
           c++; 
           } 
          } 
          fclose(file); 
    
          // Use the start of the dyn. allocated variable for the start of the heap. 
          // There is a 8 byte offset that I noticed when comparing my obtained 
          // address with the process's smap file which is why I subtract 8. (See Readme.html) 
    
          printf("\n\nThe Heap segment starts at %p\n", dynamic_var-8); 
    
          // Add the size of that variable to the start address to get the end of the heap 
    
          printf("The heap ends at %p\n\n", dynamic_var+100-8); 
    
          // Use the symbol edata to find the start of BSS 
    
          printf("The BSS segment starts after %10p \n\n", &edata); 
    
          // The end of text and start of data is the location of 
          // the single initialized global variable init. 
    
          printf("The data segment starts at %10p\n\n", &init); 
    
          //Use the address of main for the start of text. 
          // For a more accurate number, do objdump -x <filename> and 
          // look for .text in the <filename> section (see Readme.html) 
    
          printf("The start of text is approximately at %p\n\n", main); 
    
          printf("For more info, check the comments of this source code and the Readme.html\n\n"); 
    
    
          return 0; 
    
         } 
    
  • utils.c

    /* source: utils.c */ 
        /* Copyright Gerhard Rieger 2001-2009 */ 
        /* Published under the GNU General Public License V.2, see file COPYING */ 
    
        /* useful additions to C library */ 
    
        #include "config.h" 
    
        #include "sysincludes.h" 
    
        #include "compat.h" /* socklen_t */ 
        #include "mytypes.h" 
        #include "sycls.h" 
        #include "utils.h" 
    
    
        #if !HAVE_MEMRCHR 
        /* GNU extension, available since glibc 2.1.91 */ 
        void *memrchr(const void *s, int c, size_t n) { 
         const unsigned char *t = ((unsigned char *)s)+n; 
         while (--t >= (unsigned char *)s) { 
          if (*t == c) break; 
         } 
         if (t < (unsigned char *)s) 
          return NULL; 
         return (void *)t; 
        } 
        #endif /* !HAVE_MEMRCHR */ 
    
        void *memdup(const void *src, size_t n) { 
         void *dest; 
    
         if ((dest = Malloc(n)) == NULL) { 
          return NULL; 
         } 
    
         memcpy(dest, src, n); 
         return dest; 
        } 
    
        /* search the keyword-table for a match of the leading part of name. */ 
        /* returns the pointer to the matching field of the keyword or NULL if no 
         keyword was found. */ 
        const struct wordent *keyw(const struct wordent *keywds, const char *name, unsigned int nkeys) { 
         unsigned int lower, upper, mid; 
         int r; 
    
         lower = 0; 
         upper = nkeys; 
    
         while (upper - lower > 1) 
         { 
          mid = (upper + lower) >> 1; 
          if (!(r = strcasecmp(keywds[mid].name, name))) 
          { 
         return &keywds[mid]; 
          } 
          if (r < 0) 
         lower = mid; 
          else 
         upper = mid; 
         } 
         if (nkeys > 0 && !(strcasecmp(keywds[lower].name, name))) 
         { 
          return &keywds[lower]; 
         } 
         return NULL; 
        } 
    
        /* Linux: setenv(), AIX: putenv() */ 
        #if !HAVE_SETENV 
        int setenv(const char *name, const char *value, int overwrite) { 
         int result; 
         char *env; 
         if (!overwrite) { 
          if (getenv(name)) return 0; /* already exists */ 
         } 
         if ((env = Malloc(strlen(name)+strlen(value)+2)) == NULL) { 
          return -1; 
         } 
         sprintf(env, "%s=%s", name, value); 
         if ((result = putenv(env)) != 0) { /* AIX docu says "... nonzero ..." */ 
          free(env); 
          result = -1; 
         } 
         /* linux "man putenv" says: ...this string becomes part of the environment*/ 
         return result; 
        } 
        #endif /* !HAVE_SETENV */ 
    
    
    
        /* sanitize an "untrusted" character. output buffer must provide at least 5 
         characters space. 
         Does not append null. returns length out output (currently: max 4) */ 
        static size_t sanitize_char(char c, char *o, int style) { 
         int hn; /* high nibble */ 
         int ln; /* low nibble */ 
         int n; /* written chars */ 
         if (isprint(c)) { 
          *o = c; 
          return 1; 
         } 
         *o++ = '\\'; 
         n = 2; 
         switch (c) { 
         case '\0': *o++ = '0'; break; 
         case '\a': *o++ = 'a'; break; 
         case '\b': *o++ = 'b'; break; 
         case '\t': *o++ = 't'; break; 
         case '\n': *o++ = 'n'; break; 
         case '\v': *o++ = 'v'; break; 
         case '\f': *o++ = 'f'; break; 
         case '\r': *o++ = 'r'; break; 
         case '\'': *o++ = '\''; break; 
         case '\"': *o++ = '"'; break; 
         case '\\': *o++ = '\\'; break; 
         default: 
          *o++ = 'x'; 
          hn = (c>>4)&0x0f; 
          ln = c&0x0f; 
          *o++ = (hn>=10 ? (('A'-1)+(hn-10)) : ('0'+hn)); 
          *o++ = (ln>=10 ? (('A'-1)+(ln-10)) : ('0'+ln)); 
          n = 4; 
         } 
         return n; 
        } 
    
        /* sanitize "untrusted" text, replacing special control characters with the C 
         string version ("\x"), and replacing unprintable chars with ".". 
         text can grow to four times of input, so keep output buffer long enough! 
         returns a pointer to the first untouched byte of the output buffer. 
        */ 
        char *sanitize_string(const char *data, /* input data */ 
           size_t bytes, /* length of input data, >=0 */ 
           char *coded, /* output buffer, must be long enough */ 
           int style 
           ) { 
         int c; 
    
         while (bytes > 0) { 
          c = *(unsigned char *)data++; 
          coded += sanitize_char(c, coded, style); 
          --bytes; 
         } 
         return coded; 
        } 
    
        /* copies a substring out of a given buff 
         returns scratch, \0 terminated; scratch must provide len+1 bytes 
        */ 
        char *xiosubstr(char *scratch, const char *str, size_t from, size_t len) { 
         char *scratch0 = scratch; 
         str += from; 
         while (len--) { 
          *scratch++ = *str++; 
         } 
         *scratch = '\0'; 
         return scratch0; 
        } 
    
  • utils.h

         /* source: utils.h */ 
         /* Copyright Gerhard Rieger 2001-2008 */ 
         /* Published under the GNU General Public License V.2, see file COPYING     */ 
    
         #ifndef __utils_h_included 
         #define __utils_h_included 1 
    
         /* a generic name table entry */ 
         struct wordent { 
          const char *name; 
          void *desc; 
         } ; 
    
         #if !HAVE_MEMRCHR 
         extern void *memrchr(const void *s, int c, size_t n); 
         #endif 
         extern void *memdup(const void *src, size_t n); 
         #if !HAVE_SETENV 
         extern int setenv(const char *name, const char *value, int overwrite); 
         #endif /* !HAVE_SETENV */ 
    
         extern const struct wordent *keyw(const struct wordent *keywds, const char *name, unsigned int nkeys); 
    
    
         #define XIOSAN_ZERO_MASK     0x000f 
         #define XIOSAN_ZERO_DEFAULT    0x0000 
         #define XIOSAN_ZERO_DOT     0x0001 
         #define XIOSAN_ZERO_BACKSLASH_OCT_3  0x0002 
         #define XIOSAN_ZERO_BACKSLASH_OCT_4  0x0003 
         #define XIOSAN_ZERO_BACKSLASHX_HEX_UP  0x0004 
         #define XIOSAN_ZERO_BACKSLASHX_HEX_LOW 0x0005 
         #define XIOSAN_ZERO_PERCENT_HEX_UP  0x0006 
         #define XIOSAN_ZERO_PERCENT_HEX_LOW  0x0007 
         #define XIOSAN_CONTROL_MASK    0x00f0 
         #define XIOSAN_CONTROL_DEFAULT   0x0000 
         #define XIOSAN_CONTROL_DOT    0x0010 
         #define XIOSAN_CONTROL_BACKSLASH_OCT_3 0x0020 
         #define XIOSAN_CONTROL_BACKSLASH_OCT_4 0x0030 
         #define XIOSAN_CONTROL_BACKSLASHX_HEX_UP 0x0040 
         #define XIOSAN_CONTROL_BACKSLASHX_HEX_LOW 0x0050 
         #define XIOSAN_CONTROL_PERCENT_HEX_UP  0x0060 
         #define XIOSAN_CONTROL_PERCENT_HEX_LOW 0x0070 
         #define XIOSAN_UNPRINT_MASK    0x0f00 
         #define XIOSAN_UNPRINT_DEFAULT   0x0000 
         #define XIOSAN_UNPRINT_DOT    0x0100 
         #define XIOSAN_UNPRINT_BACKSLASH_OCT_3 0x0200 
         #define XIOSAN_UNPRINT_BACKSLASH_OCT_4 0x0300 
         #define XIOSAN_UNPRINT_BACKSLASHX_HEX_UP 0x0400 
         #define XIOSAN_UNPRINT_BACKSLASHX_HEX_LOW 0x0500 
         #define XIOSAN_UNPRINT_PERCENT_HEX_UP  0x0600 
         #define XIOSAN_UNPRINT_PERCENT_HEX_LOW 0x0700 
         #define XIOSAN_DEFAULT_MASK    0xf000 
         #define XIOSAN_DEFAULT_BACKSLASH_DOT  0x1000 
         #define XIOSAN_DEFAULT_BACKSLASH_OCT_3 0x2000 
         #define XIOSAN_DEFAULT_BACKSLASH_OCT_4 0x3000 
         #define XIOSAN_DEFAULT_BACKSLASHX_HEX_UP 0x4000 
         #define XIOSAN_DEFAULT_BACKSLASHX_HEX_LOW 0x5000 
         #define XIOSAN_DEFAULT_PERCENT_HEX_UP  0x6000 
         #define XIOSAN_DEFAULT_PERCENT_HEX_LOW 0x7000 
    
         extern 
         char *sanitize_string(const char *data, /* input data */ 
            size_t bytes, /* length of input data, >=0 */ 
            char *coded, /* output buffer, must be long enough */ 
            int style); 
         extern 
         char *xiosubstr(char *scratch, const char *str, size_t from, size_t len); 
    
         #endif /* !defined(__utils_h_included) */ 
    
  • fifo.c

         /* 
         * fifo.c 
         * 
         * A simple FIFO implementation. 
         * 
         * Copyright (C) 2010, Marek Polacek <[email protected]> 
         */ 
    
         #include <stdio.h> 
         #include <stdlib.h> 
         #include <string.h> 
         #include "fifo.h" 
         #include "utils.h" 
    
         void fifo_put(fifo_t *fifo, char *data, size_t size) 
         { 
          struct item *i; 
          i = malloc(sizeof(*i)); 
          if (!i) { 
           perror("malloc"); 
           exit(EXIT_FAILURE); 
          } 
    
          if (size) { 
           data = memdup(data, size); 
           if (!data) { 
            fputs("fatal: out of memory\n", stderr); 
            free(i); 
            exit(EXIT_FAILURE); 
           } 
          } 
    
          i->next = NULL; 
          i->buf = data; 
    
          if (!fifo->tail) { 
           fifo->head = i; 
           fifo->tail = i; 
          } else { 
           fifo->tail->next = i; 
           fifo->tail = i; 
          } 
         } 
    
         char *fifo_get(fifo_t *fifo) 
         { 
          struct item *i; 
          char *data; 
    
          assert(fifo != NULL); 
          if (fifo_empty(fifo)) 
           return NULL; 
    
          i = fifo->head; 
          data = i->buf; 
    
          fifo->head = i->next; 
          if (!fifo->head) 
           fifo->tail = NULL; 
          free(i); 
    
          return data; 
         } 
    
         void fifo_free(fifo_t *fifo) 
         { 
          assert(fifo != NULL); 
          while (fifo->head) 
           (void) fifo_get(fifo); 
          free(fifo); 
         } 
    
         fifo_t *fifo_init(void) 
         { 
          fifo_t *fifo; 
          fifo = malloc(sizeof(*fifo)); 
          if (!fifo) { 
           perror("malloc"); 
           exit(EXIT_FAILURE); 
          } 
    
          fifo->head = NULL; 
          fifo->tail = NULL; 
          return fifo; 
         } 
    
  • fifo.h

         /* 
         * fifo.h 
         * 
         * A simple FIFO implementation. 
         * 
         * Copyright (C) 2010, Marek Polacek <[email protected]> 
         */ 
    
         #ifndef FIFO_H 
         #define FIFO_H 
    
         #include <assert.h> 
    
         struct item { 
          char *buf; 
          struct item *next; 
         }; 
    
         struct fifo { 
          struct item *head; 
          struct item *tail; 
         }; 
    
         typedef struct fifo fifo_t; 
    
         extern fifo_t *fifo_init(void); 
         extern void fifo_free(fifo_t *); 
         extern char *fifo_get(fifo_t *); 
         extern void fifo_put(fifo_t *, char *, size_t); 
    
         static inline int fifo_empty(fifo_t *fifo) 
         { 
          return (fifo->head == NULL); 
         } 
    
         static inline char *fifo_peek(fifo_t *fifo) 
         { 
          assert(fifo != NULL); 
          if (!fifo_empty(fifo)) 
           return fifo->head->buf; 
          else 
           return NULL; 
         } 
    
         #endif /* FIFO_H */ 
    

回答

0

編譯器的當前調用根本就沒有意義了(寫輸出到C文件?什麼是-util?)。 Read something up on C compilation。你需要將所有的目標文件鏈接在一起,所以像

gcc -o myprog myprog.c util.c 

就足夠了。

+0

這沒有做到這一點... –

0

你的gcc命令行不太正確。 試着這麼做:

gcc *.c -o mini2

或者你可以首先單獨編譯它們,然後連結在一起,

gcc -c fifo.c gcc -c utils.c gcc -c mini2.c gcc -o mini2 mini2.o fifo.o utils.o

您可能需要閱讀有關編譯和用gcc和ld鏈接。