我的目录中有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
足够了。