2014-05-23 17 views
2

我不断收到此错误,我不知道为什么。我失去了我的想法试图使这项工作,任何帮助将不胜感激。试图使原子记录工作

clang: error: linker command failed with exit code 1

代码:

1 #include <stdio.h> 
2 #include <stdlib.h> 
3 #include <string.h> 
4 #include <unistd.h> 
5 #include "atomic_logger.h" 
6 
7 #define BUFSIZE 1024 
8 
9 int main (int argc, char *argv[]) { 
10 char buf[BUFSIZE]; 
11 pid_t childpid = 0; 
12 int i, n; 
13 
14 if (argc != 3){  /* check for valid number of command-line arguments */ 
15  fprintf (stderr, "Usage: %s processes filename\n", argv[0]); 
16  return 1; 
17 } 
18 n = atoi(argv[1]);        /* create a process chain */ 
19 for (i = 1; i < n; i++) 
20  if ((childpid = fork())) 
21   break; 
22 if (childpid == -1) { 
23  perror("Failed to fork"); 
24  return 1; 
25 } 
26 
27 if (atomic_log_open(argv[2]) == -1) {    /* open atomic log file */ 
28  fprintf(stderr, "Failed to open log file"); 
29  return 1; 
30 } 
31         /* log the output, using two different forms */ 
32 atomic_log_printf("i:%d process:%ld", i, (long)getpid()); 
33 
34 atomic_log_printf(" parent:%ld child:%ld\n", (long)getppid(), (long)childpid); 
35 
36 
37 if (atomic_log_send() == -1) { 
38  fprintf(stderr, "Failed to send to log file"); 
39  return 1; 
40 } 
41 atomic_log_close(); 
42 return 0; 
43 } 

是的,这是一所学校任务的一部分,但我并不需要帮助编码,我需要帮助编译。为什么不能编译?我把atomic_logger.c和atomic_logger.h放到与这个文件相同的文件夹中,以防万一,但我仍然得到这个错误。出了什么问题? atomic_logger.h如下:

​​

和atomic_logger.c如下:

1 #include <errno.h> 
    2 #include <fcntl.h> 
    3 #include <stdarg.h> 
    4 #include <stdio.h> 
    5 #include <stdlib.h> 
    6 #include <string.h> 
    7 #include <unistd.h> 
    8 #include <sys/stat.h> 
    9 
10 #define FILE_PERMS (S_IRUSR | S_IWUSR| S_IRGRP | S_IROTH) 
11 #define OPEN_FLAGS (O_WRONLY|O_APPEND|O_CREAT) 
12 typedef struct list { 
13 char *entry; 
14 int len; 
15 struct list *next; 
16 } list; 
17 
18 static int fd = -1; 
19 static list *first = NULL; 
20 static list *last = NULL; 
21 
22 
23 /* ----------------------------------------------------------------- 
24 Private Functions 
25 */ 
26 
27 /* This is the same as write, but restarts if interrupted by a signal */ 
28 static ssize_t my_write(int fd, void *buf, size_t size) { 
29 ssize_t bytes; 
30 
31 while (((bytes = write(fd, buf, size)) == -1) && (errno == EINTR)); 
32 return bytes; 
33 } 
34 
35 /* Insert an entry with the given len field, but allocate extra bytes.*/ 
36 /* Return a pointer to the new entry on success or NULL on failure. */ 
37 static list *insert_new_entry(int len, int extra) { 
38 char *new_str; 
39 list *new_entry; 
40 
41 new_entry = (list *)malloc(sizeof(list)+len+extra); 
42 if (new_entry == NULL) 
43  return NULL; 
44 new_str = (char *)new_entry+sizeof(list); 
45 new_entry->entry = new_str; 
46 new_entry->next = NULL; 
47 new_entry->len = len; 
48 if (last == NULL) 
49  first = new_entry; 
50 else 
51  last->next = new_entry; 
52 last = new_entry; 
53 return new_entry; 
54 } 
55 
56 /* Return the sum of the lengths of all the entries.     */ 
57 static int get_length() { 
58 int len = 0; 
59 list *current; 
60 
61 current = first; 
62 while (current != NULL) { 
63  len += current->len; 
64  current = current->next; 
65 } 
66 return len; 
67 } 
68 
69 /* Clear the list and free all the space.        */ 
70 static void clear() { 
71 list *current; 
72 list *free_entry; 
73 
74 current = first; 
75 while (current != NULL) { 
76  free_entry = current; 
77  current = current->next; 
78  free(free_entry); 
79 } 
80 first = NULL; 
81 last = NULL; 
82 } 
83 
84 /* ----------------------------------------------------------------- 
85 Public Functions 
86 */ 
87 
88 /* Open the given file for logging.         */ 
89 /* If successful, return 0. Otherwise, return -1 with errno set.  */ 
90 int atomic_log_open(char *fn) { 
91 while (fd = open(fn, OPEN_FLAGS, FILE_PERMS), fd == -1 && errno == EINTR); 
92 if (fd < 0) 
93  return -1; 
94 return 0; 
95 } 
96 
97 /* Insert the given array with given size in the list.    */ 
98 /* If successful, return 0. Otherwise, return -1 with errno set.  */ 
99 int atomic_log_array(char *s, int len) { 
100 list *new_entry; 
100 list *new_entry; 
101 
102 if (fd < 0) { 
103  errno = EINVAL; 
104  return -1; 
105 } 
106 new_entry = insert_new_entry(len, 0); 
107 if (new_entry == NULL) 
108  return -1; 
109 (void)memcpy(new_entry->entry, s, len); 
110 return 0; 
111 } 
112 
113 /* Insert the given string in the list.        */ 
114 /* Do not include the string terminator.        */ 
115 /* If successful, return 0. Otherwise, return -1 with errno set.  */ 
116 int atomic_log_string(char *s) { 
117 return atomic_log_array(s, strlen(s)); 
118 } 
119 
120 /* Insert an entry in the list.          */ 
121 /* The syntax is similar to printf.         */ 
122 /* Include the string terminator but do not count it in the length. */ 
123 /* If successful, return 0. Otherwise, return -1 with errno set.  */ 
124 int atomic_log_printf(char *fmt, ...) { 
125 va_list ap; 
126 char ch; 
127 int len; 
128 list *new_entry; 
129 
130 if (fd < 0) { 
131  errno = EINVAL; 
132  return -1; 
133 } 
134 va_start(ap, fmt); 
135 len = vsnprintf(&ch, 1, fmt, ap); 
136 new_entry = insert_new_entry(len, 1); 
137 if (new_entry == NULL) 
138  return -1; 
139 vsprintf(new_entry->entry, fmt, ap); 
140 return 0; 
141 } 
142 
143 /* Attempt to log the entire list with a single write.    */ 
144 /* Clear the list if successful.          */ 
145 /* If successful, return 0. Otherwise, return -1 with errno set.  */ 
146 /* If the entire list cannot be logged with a single write, this is */ 
147 /* considered a failure.           */ 
148 int atomic_log_send() { 
149 char *buf; 
150 list *current; 
151 int len; 
152 
153 if (fd < 0) { 
154  errno = EINVAL; 
155  return -1; 
156 } 
157 len = get_length(); 
158 if (len == 0) 
159  return 0; 
160 buf = (char *)malloc(len); 
161 if (buf == NULL) 
162  return -1; 
163 current = first; 
164 len = 0; 
165 while (current != NULL) { 
166  (void)memcpy(buf+len, current->entry, current->len); 
167  len += current->len; 
168  current = current->next; 
169 } 
170 if (my_write(fd, buf, len) != len) { 
171  free(buf); 
172  errno = EAGAIN; 
173  return -1; 
174 } 
175 free(buf); 
176 clear(); 
177 return 0; 
178 } 
179 
180 /* Clear the list and free all the space without logging anything. */ 
181 int atomic_log_clear() { 
182 clear(); 
183 return 0; 
184 } 
185 
186 /* Close the log file. Any data not yet logged is lost.    */ 
187 int atomic_log_close() { 
188 int retval; 
189 clear(); 
190 while (retval = close(fd), retval == -1 && errno == EINTR) ; 
191 return retval; 
192 } 

事情看起来宣布适当给我,但我敢肯定有一些东西很明显我缺少的,因为该错误消息我得到的是:

imacbook:lab4 smythe1$ gcc -o ex8/chainforkopenlog ex8/chainforkopenlog.c 
Undefined symbols for architecture x86_64: 
    "_atomic_log_close", referenced from: 
     _main in chainforkopenlog-44aa15.o 
    "_atomic_log_open", referenced from: 
     _main in chainforkopenlog-44aa15.o 
    "_atomic_log_printf", referenced from: 
     _main in chainforkopenlog-44aa15.o 
    "_atomic_log_send", referenced from: 
     _main in chainforkopenlog-44aa15.o 
ld: symbol(s) not found for architecture x86_64 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

预先感谢帮助我解决这个问题...

回答

2

你永远不要告诉gcc编译atomic_logger.c,或者反对它。

最简单的补救办法是

$ gcc -o ex8/chainforkopenlog ex8/chainforkopenlog.c ex8/atomic_logger.c 

这告诉gcc编译所有列出.c文件和链接他们一起为最终输出二进制 - 在一个调用。

另一种方法是编译仅每个.c文件独立地其使用-c开关对应.o文件。然后链接所有的.o文件一起用于输出二进制文件。

$ gcc -c ex8/chainforkopenlog.c  # Produces chainforkopenlog.o 
$ gcc -c ex8/atomic_logger.c   # Produces atomic_logger.o 

$ gcc -o ex8/chainforkopenlog chainforkopenlog.o atomic_logger.o 

注意#include "atomic_logger.h"没有什么做最后的链接过程 - 它不会自动地通知GCC看atomic_logger.c。它只是复制+粘贴该头文件的内容在它所在的位置。

+1

谢谢乔纳森,这解决了这个问题。我知道这显然很明显。 –