Yes, this question has been asked many times, and I've been looking and reading forums, and SO posts, but the answers are all unrelated (or so they seem) to this one. So, I have this main file :
是的,这个问题已经被问过很多次了,我一直在寻找和阅读论坛,所以帖子,但是答案都是毫无关联的(或者看起来是这样)。我有一个主文件:
-- sgbd_server.c --
——sgbd_server。c——
#include "sgbd_server.h"
/**
* Open server pipe and return handle. -1 = error
*/
int open_server_pipe() {
return pipe_open(FIFO_NAME, O_RDONLY, S_CON_COLOR);
}
/**
* Close server pipe
*/
void close_server_pipe(int fd) {
pipe_close(fd, FIFO_NAME, S_CON_COLOR);
}
int main(int argc, char *argv[]) {
int pipe_fd;
pipe_fd = open_server_pipe();
if (pipe_fd == -1) {
perror("Cannot open pipe");
}
close_server_pipe(pipe_fd);
exit(EXIT_SUCCESS);
}
Then the header files :
然后头文件:
-- sgbd_server.h --
——sgbd_server。h——
#include "common.h"
#define FIFO_NAME "./sgbd_server_pipe"
#define BUFFER_SIZE PIPE_BUF
#define S_CON_COLOR 1 /* C_COLOR_RED */
-- common.h --
——常见。h——
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "console.h"
#define CLIENT_FIFO_PREFIX = "./sgbd_client_"
int pipe_open(char *f, int mode, int color);
void pipe_close(int pipe_fd, char *f, int color);
The two functions pipe_open
and pipe_close
are defined in pipe.c
and are basically returning 0
and void
. This last file is compiled separately in the Make file.
管道中定义了两个函数pipe_open和pipe_close。c基本上返回0和void。最后一个文件在Make文件中单独编译。
I'm not a guru at making Make files, but for the sake of this question, here it is :
我不是制作文件的专家,但是为了这个问题,这里是:
SERVER = sgbd_server
CLIENT = sgbd_client
CC = gcc
C_FLAGS = -Wall -I.
LINKER = gcc
L_FLAGS = -Wall -l pthread -Wall -I.
RM = rm -f
client: sgbd_client.o pipe.o console.o
@echo -n "Building client... "
@$(LINKER) $(L_FLAGS) -o $(CLIENT) sgbd_client.o pipe.o console.o
@echo "Complete!\n"
server: sgbd_server.o pipe.o console.o
@echo -n "Building server... "
@$(LINKER) $(L_FLAGS) -o $(SERVER) sgbd_server.o pipe.o console.o
@echo "Complete!\n"
sgbd_client.o: sgbd_client.c
@echo -n "Refreshing client sources... "
@$(CC) $(C_FLAGS) -c sgbd_client.c
@echo "Done!"
sgbd_server.o: sgbd_server.c common.h
@echo -n "Refreshing server sources..."
@$(CC) $(C_FLAGS) -c sgbd_server.c common.h
@echo "Done!"
pipe.o: pipe.c
@echo -n "Refreshing pipe sources..."
@$(CC) $(C_FLAGS) -c pipe.c
@echo "Done!"
console.o: console.c
@echo -n "Refreshing console sources..."
@$(CC) $(C_FLAGS) -c console.c
@echo "Done!"
clean:
@echo -n "Cleaning up executables and object files... "
@$(RM) $(SERVER) $(CLIENT) *.o
@echo "Ok\n"
** NOTE ** : the file console.c
and implements some functions to control I/O on the console, nothing fancy. As you see, it is also compiled separately.
**注释**:文件控制台。并实现一些功能来控制控制台的I/O,没有什么特别的。如您所见,它也是单独编译的。
Now, when I type make client
, all is well and birds are signing, etc. etc. But when I type make server
, it spits out
现在,当我打字的时候,一切都很好,小鸟也在签名,等等。但是当我打字的时候,它就会跳出来。
sgbd_server.c: In function ‘open_server_pipe’:
sgbd_server.c:7: warning: implicit declaration of function ‘pipe_open’
sgbd_server.c: In function ‘close_server_pipe’:
sgbd_server.c:14: warning: implicit declaration of function ‘pipe_close’
I'm running GCC on a Linux amd64 if it makes any difference (I doubt it).
我在Linux amd64上运行GCC,如果它有什么不同(我对此表示怀疑)。
Now, why would it warn me about that? The two functions are declared in common.h
, which is included in sgbd_server.h
... What am I missing here?
为什么要警告我呢?这两个函数是相同的。h,包含在sgbd_server.h…我错过了什么?
Thank you for your time!
感谢您的时间!
** UPDATE **
* * * *更新
Thank you everyone for your suggestion. I did try to find if there would be a file common.h
somewhere else in my include path that would be included somehow... While I failed to find any that would have slipped in the compilation process instead of the local common.h
(sig) I found some .ghc
files sitting in my source folder. Since they are not cleaned by make clean
, I deleted manually those files. Guess what? No warning. What are those files and why are they created?
谢谢大家的建议。我确实试着找出是否有一个文件是通用的。在我的包含路径中其他地方也会被包括进来…虽然我没有发现在编译过程中会有任何遗漏,而不是在本地通用。h (sig)我在我的源文件夹中找到了一些。ghc文件。由于没有清理干净,所以我手动删除了这些文件。你猜怎么着?没有警告。这些文件是什么,为什么要创建?
4 个解决方案
#1
4
For a start, I don't think it's a good idea to be giving common.h
to the compiler in the makefile:
首先,我不认为这样做是个好主意。h到makefile中的编译器:
@$(CC) $(C_FLAGS) -c sgbd_server.c common.h
This would be better as just:
这样做会更好:
@$(CC) $(C_FLAGS) -c sgbd_server.c
Header files are usually incorporated with just an #include
. You appear to be telling the compiler to try and compile common.h
as a standalone C file. That's one difference between the client and server compile commands and you should fix it.
头文件通常只包含一个#include。您似乎在告诉编译器尝试编译普通的代码。h作为一个独立的C文件。这是客户机和服务器编译命令之间的一个区别,您应该修复它。
The only other thing I can suggest is that you may not be getting the header files you think you're getting. Start by putting the line:
我唯一可以建议的是,你可能没有得到你认为你得到的头文件。开始的时候,你应该说:
#error Urk! in common.h
at the top of your common.h
and ensure the build fails there.
在你的共同之处。确保构建失败。
If not, then that file is coming from somewhere else. You may also want to do the same thing with your sgbd_server.h
file as well.
如果没有,那么该文件将来自其他地方。您可能还想对sgbd_server执行同样的操作。h文件。
Based on your edit:
基于你的编辑:
I found some .ghc files sitting in my source folder. Since they are not cleaned by make clean, I deleted manually those files. Guess what? No warning. What are those files and why are they created?
我在源文件夹中找到了一些。ghc文件。由于没有清理干净,所以我手动删除了这些文件。你猜怎么着?没有警告。这些文件是什么,为什么要创建?
These are, assuming ghc
was a typo and you meant gch
, pre-compiled headers generated by gcc
, at least in part to speed up the compilation process. Rather than having to process a header file many times during a build (once per source file that includes it), pre-compiling it once and using the pre-compiled version is a lot more efficient.
假设ghc是一个typo,而您的意思是gch,由gcc生成的预编译头文件,至少在一定程度上是为了加速编译过程。在构建过程中(每个源文件包含它),不必多次处理头文件,而是一次编译一次并使用预编译版本的效率要高得多。
I think this was most likely cause by the fact that you included common.h
on your compiler command line when you did the server. By default, header files given directly to gcc
will be turned into pre-compiled header files and used in preference after that point. To test this, I created a qq.h
file and executed gcc qq.h
and out popped qq.h.gch
.
我认为这很有可能是因为你包括了普通的人。当你做服务器时,在你的编译器命令行。默认情况下,直接向gcc提供的头文件将被转换成预编译的头文件,并在以后使用。为了测试这个,我创建了一个qq。h文件并执行gcc qq。轰的一声,砰的一声。
It's quite likely, given that deleting them solved your problem, that these files were somehow causing your issues (be that the presence of pre-compiled headers older than the real headers or something else entirely). There's a good chance that your compile line:
很有可能,由于删除它们解决了您的问题,这些文件在某种程度上导致了您的问题(即预编译头的存在比真正的头文件或其他内容更早)。你的编译行很有可能:
@$(CC) $(C_FLAGS) -c sgbd_server.c common.h
would first compile the server program, including the old precompiled header, then make a new precompiled header out of the newer header file.
首先编译服务器程序,包括旧的预编译头文件,然后从新的头文件中生成一个新的预编译头。
That's probably why a change to common.h
had no (immediate) effect. You would have to make ; touch common.h ; make
to ensure the newer pre-compiled header file was used in the server program.
这可能就是为什么要改变公共关系的原因。h没有(立即)效果。你需要做;常见的联系。h;确保在服务器程序中使用更新的预编译头文件。
Whether you want to track it back to the root cause and get a proper explanation is a matter of taste - there's a school of thought that you should sometimes just record how you fixed it and not worry too much, lest you become entangled in the very nature of reality itself.
是否需要跟踪的根源和得到一个适当的解释是一种味道——有学校认为你应该有时只是记录你怎么固定,不要担心太多,以免成为现实本身的本质的纠缠。
Not me of course, I'm the personality type that will attempt to track my problems back to the individual sub-atomic particle that caused it, but sometimes pragmatism requires me to let it go :-)
当然不是我,我是那种会试图将我的问题追溯回导致它的亚原子粒子的人格类型,但有时候实用主义要求我放弃它:-)
#2
1
observations: you have an = in a #define which I suspect you don't mean to have there
观察:你有一个#定义,我怀疑你不是有意的。
#define CLIENT_FIFO_PREFIX = "./sgbd_client_"
should perhaps be
也许应该
#define CLIENT_FIFO_PREFIX "./sgbd_client_"
comments: I've occasionally witnessed strange behavior from compilers when a prototype contains formal parameter names (in addition to the mandatory types) and the definition of the function uses different formal parameter names. ie. in your pipes.c Does you pipes.c include common.h?
注释:当原型包含正式的参数名称(除了强制类型之外)时,我偶尔会看到编译器的奇怪行为,而函数的定义使用不同的形式参数名。ie。在你的管道。c你管道。包括构成?
Also, conditional guards #ifndef headerfilename #define headerfilename #endif are a good practise, but that is not directly related to your problem.
另外,条件保护#ifndef headerfilename #define headerfilename #endif是一个很好的练习,但这与您的问题没有直接关系。
.PMCD.
.PMCD。
#3
0
I suspect you might have another file called common.h that's getting included instead of the file you expect. I copy and pasted your files and it compiled with no warning.
我怀疑您可能有另一个名为common的文件。这是被包含的,而不是你期望的文件。我复制粘贴了你的文件,没有任何警告。
#4
0
The includes in the files you posted look like they should work. A few ideas what else could be wrong:
你发布的文件中包含的内容看起来应该是有用的。有一些想法可能是错误的:
- Does
common.h
orconsole.h
try to includesgbd_server.h
, so that you end up with circular includes? - 是常见的。h或控制台。h尝试包含sgbd_server。h,所以最后得到循环包含?
- Do you use include guards (or even other
#ifdef
s) and maybe mixed them up somewhere, so that one of the files is excluded unintentionally? - 您是否使用了包括警卫(甚至其他#ifdefs),并可能将它们混合到某个地方,这样就会无意中排除其中一个文件?
- Do you have another
common.h
somewhere in you include path that might get included instead of the one that you intended? - 你还有其他共同点吗?在你的某个地方,包括可能被包含的路径,而不是你想要的路径?
#1
4
For a start, I don't think it's a good idea to be giving common.h
to the compiler in the makefile:
首先,我不认为这样做是个好主意。h到makefile中的编译器:
@$(CC) $(C_FLAGS) -c sgbd_server.c common.h
This would be better as just:
这样做会更好:
@$(CC) $(C_FLAGS) -c sgbd_server.c
Header files are usually incorporated with just an #include
. You appear to be telling the compiler to try and compile common.h
as a standalone C file. That's one difference between the client and server compile commands and you should fix it.
头文件通常只包含一个#include。您似乎在告诉编译器尝试编译普通的代码。h作为一个独立的C文件。这是客户机和服务器编译命令之间的一个区别,您应该修复它。
The only other thing I can suggest is that you may not be getting the header files you think you're getting. Start by putting the line:
我唯一可以建议的是,你可能没有得到你认为你得到的头文件。开始的时候,你应该说:
#error Urk! in common.h
at the top of your common.h
and ensure the build fails there.
在你的共同之处。确保构建失败。
If not, then that file is coming from somewhere else. You may also want to do the same thing with your sgbd_server.h
file as well.
如果没有,那么该文件将来自其他地方。您可能还想对sgbd_server执行同样的操作。h文件。
Based on your edit:
基于你的编辑:
I found some .ghc files sitting in my source folder. Since they are not cleaned by make clean, I deleted manually those files. Guess what? No warning. What are those files and why are they created?
我在源文件夹中找到了一些。ghc文件。由于没有清理干净,所以我手动删除了这些文件。你猜怎么着?没有警告。这些文件是什么,为什么要创建?
These are, assuming ghc
was a typo and you meant gch
, pre-compiled headers generated by gcc
, at least in part to speed up the compilation process. Rather than having to process a header file many times during a build (once per source file that includes it), pre-compiling it once and using the pre-compiled version is a lot more efficient.
假设ghc是一个typo,而您的意思是gch,由gcc生成的预编译头文件,至少在一定程度上是为了加速编译过程。在构建过程中(每个源文件包含它),不必多次处理头文件,而是一次编译一次并使用预编译版本的效率要高得多。
I think this was most likely cause by the fact that you included common.h
on your compiler command line when you did the server. By default, header files given directly to gcc
will be turned into pre-compiled header files and used in preference after that point. To test this, I created a qq.h
file and executed gcc qq.h
and out popped qq.h.gch
.
我认为这很有可能是因为你包括了普通的人。当你做服务器时,在你的编译器命令行。默认情况下,直接向gcc提供的头文件将被转换成预编译的头文件,并在以后使用。为了测试这个,我创建了一个qq。h文件并执行gcc qq。轰的一声,砰的一声。
It's quite likely, given that deleting them solved your problem, that these files were somehow causing your issues (be that the presence of pre-compiled headers older than the real headers or something else entirely). There's a good chance that your compile line:
很有可能,由于删除它们解决了您的问题,这些文件在某种程度上导致了您的问题(即预编译头的存在比真正的头文件或其他内容更早)。你的编译行很有可能:
@$(CC) $(C_FLAGS) -c sgbd_server.c common.h
would first compile the server program, including the old precompiled header, then make a new precompiled header out of the newer header file.
首先编译服务器程序,包括旧的预编译头文件,然后从新的头文件中生成一个新的预编译头。
That's probably why a change to common.h
had no (immediate) effect. You would have to make ; touch common.h ; make
to ensure the newer pre-compiled header file was used in the server program.
这可能就是为什么要改变公共关系的原因。h没有(立即)效果。你需要做;常见的联系。h;确保在服务器程序中使用更新的预编译头文件。
Whether you want to track it back to the root cause and get a proper explanation is a matter of taste - there's a school of thought that you should sometimes just record how you fixed it and not worry too much, lest you become entangled in the very nature of reality itself.
是否需要跟踪的根源和得到一个适当的解释是一种味道——有学校认为你应该有时只是记录你怎么固定,不要担心太多,以免成为现实本身的本质的纠缠。
Not me of course, I'm the personality type that will attempt to track my problems back to the individual sub-atomic particle that caused it, but sometimes pragmatism requires me to let it go :-)
当然不是我,我是那种会试图将我的问题追溯回导致它的亚原子粒子的人格类型,但有时候实用主义要求我放弃它:-)
#2
1
observations: you have an = in a #define which I suspect you don't mean to have there
观察:你有一个#定义,我怀疑你不是有意的。
#define CLIENT_FIFO_PREFIX = "./sgbd_client_"
should perhaps be
也许应该
#define CLIENT_FIFO_PREFIX "./sgbd_client_"
comments: I've occasionally witnessed strange behavior from compilers when a prototype contains formal parameter names (in addition to the mandatory types) and the definition of the function uses different formal parameter names. ie. in your pipes.c Does you pipes.c include common.h?
注释:当原型包含正式的参数名称(除了强制类型之外)时,我偶尔会看到编译器的奇怪行为,而函数的定义使用不同的形式参数名。ie。在你的管道。c你管道。包括构成?
Also, conditional guards #ifndef headerfilename #define headerfilename #endif are a good practise, but that is not directly related to your problem.
另外,条件保护#ifndef headerfilename #define headerfilename #endif是一个很好的练习,但这与您的问题没有直接关系。
.PMCD.
.PMCD。
#3
0
I suspect you might have another file called common.h that's getting included instead of the file you expect. I copy and pasted your files and it compiled with no warning.
我怀疑您可能有另一个名为common的文件。这是被包含的,而不是你期望的文件。我复制粘贴了你的文件,没有任何警告。
#4
0
The includes in the files you posted look like they should work. A few ideas what else could be wrong:
你发布的文件中包含的内容看起来应该是有用的。有一些想法可能是错误的:
- Does
common.h
orconsole.h
try to includesgbd_server.h
, so that you end up with circular includes? - 是常见的。h或控制台。h尝试包含sgbd_server。h,所以最后得到循环包含?
- Do you use include guards (or even other
#ifdef
s) and maybe mixed them up somewhere, so that one of the files is excluded unintentionally? - 您是否使用了包括警卫(甚至其他#ifdefs),并可能将它们混合到某个地方,这样就会无意中排除其中一个文件?
- Do you have another
common.h
somewhere in you include path that might get included instead of the one that you intended? - 你还有其他共同点吗?在你的某个地方,包括可能被包含的路径,而不是你想要的路径?