我的目录中有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函数对编译器可见吗?我在目录中的文件是:


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;

        }

实用程序

    /* 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;
    }

实用程序

                        /* 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
         *
         * 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 */

最佳答案

当前对编译器的调用根本没有意义(将输出写入C文件?什么是-util?)。 Read something up on C compilation。您需要将所有目标文件链接在一起,所以类似

gcc -o myprog myprog.c util.c


足够了。

10-08 16:15