我在一个目录中有 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 */