0

我在一个目录中有 5 个文件。我正在尝试使用编译我的程序gcc -o mini2.c -pthread -utils,但出现以下错误:

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

有什么想法可以让编译器可以看到 memdup 函数吗?我在目录中的文件是:

  • 迷你2.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;
    
            }
    
  • 实用程序.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;
        }
    
  • 实用程序.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 <xpolac06@stud.fit.vutbr.cz>
             */
    
            #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 <xpolac06@stud.fit.vutbr.cz>
             */
    
            #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 */
    
4

2 回答 2

0

编译器的当前调用根本没有意义(将输出写入 C 文件?什么是-util?)。阅读有关 C 编译的内容。您需要将所有目标文件链接在一起,所以像

gcc -o myprog myprog.c util.c

就足够了。

于 2013-02-03T17:56:45.717 回答
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 进行编译和链接的信息。

于 2013-02-03T17:58:10.163 回答