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関数をコンパイラに見えるようにする方法はありますか? ディレクトリにあるファイルは次のとおりです。

  • 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;
        }
    
  • ユーティリティ.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 に答える