1

是的,这个问题已经被问过很多次了,我一直在寻找和阅读论坛和 SO 帖子,但答案都与这个问题无关(或者看起来如此)。所以,我有这个文件:

-- 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);
}

然后头文件:

-- 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 --

#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);

两个函数pipe_openandpipe_close定义在pipe.cand 中,基本上是返回0and void。最后一个文件在 Make 文件中单独编译。

我不是制作 Make 文件的专家,但为了这个问题,这里是:

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"

**注意** :该文件console.c并实现了一些功能来控制控制台上的 I/O,没什么花哨的。如您所见,它也是单独编译的。

现在,当我输入时make client,一切都很好,鸟儿在签名等等。但是当我输入时make server,它会吐出来

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’

如果有任何区别,我正在 Linux amd64 上运行 GCC(我对此表示怀疑)。

现在,它为什么要警告我呢?这两个函数在 中声明common.h,包含在sgbd_server.h... 我在这里缺少什么?

感谢您的时间!

**更新**

谢谢大家的建议。我确实尝试过在我的包含路径中的其他地方是否会有一个文件common.h以某种方式包含在内......虽然我没有找到任何会在编译过程中滑倒而不是本地common.hsig)的文件,但我找到了一些.ghc文件坐在我的源文件夹中。由于它们没有被清理make clean,我手动删除了这些文件。你猜怎么了?没有警告。这些文件是什么,为什么要创建它们?

4

4 回答 4

4

首先,我认为common.h在 makefile 中提供给编译器不是一个好主意:

@$(CC) $(C_FLAGS) -c sgbd_server.c common.h

这会更好:

@$(CC) $(C_FLAGS) -c sgbd_server.c

头文件通常只包含一个#include. 您似乎在告诉编译器尝试编译common.h为独立的 C 文件。这是客户端和服务器编译命令之间的区别之一,您应该修复它。

我唯一可以建议的另一件事是,您可能没有获得您认为获得的头文件。首先放置一行:

#error Urk! in common.h

在您的顶部common.h并确保构建在那里失败。

如果不是,那么该文件来自其他地方。您可能还想对您的sgbd_server.h文件做同样的事情。


根据您的编辑:

我在我的源文件夹中发现了一些 .ghc 文件。由于 make clean 没有清理它们,因此我手动删除了这些文件。你猜怎么了?没有警告。这些文件是什么,为什么要创建它们?

这些是,假设ghc是一个错字,你的意思是gch,由 生成的预编译头文件gcc,至少部分是为了加快编译过程。无需在构建期间多次处理头文件(每个包含它的源文件一次),预编译一次并使用预编译版本效率更高。

我认为这很可能是由于您common.h在执行服务器时包含在编译器命令行中的事实。默认情况下,直接给出的头文件gcc将被转换为预编译的头文件,并在此之后优先使用。为了测试这一点,我创建了一个qq.h文件并执行gcc qq.h并弹出了qq.h.gch.

鉴于删除它们解决了您的问题,很有可能这些文件以某种方式导致了您的问题(例如存在比实际头文件更早的预编译头文件或完全其他的东西)。您的编译行很有可能:

@$(CC) $(C_FLAGS) -c sgbd_server.c common.h

将首先编译服务器程序,包括旧的预编译头文件,然后从较新的头文件中制作一个新的预编译头文件。

这可能就是为什么更改为common.h没有(立即)效果的原因。您必须make ; touch common.h ; make确保在服务器程序中使用了较新的预编译头文件。

你是否想追根溯源并得到正确的解释是一个品味问题——有一种观点认为,有时你应该记录下你是如何修复它的,不要太担心,以免你陷入困境。现实本身的本质。

当然不是我,我是那种会试图将我的问题追溯到导致它的单个亚原子粒子的性格类型,但有时实用主义要求我放手:-)

于 2010-11-16T02:04:11.333 回答
1

观察:你在#define 中有一个=,我怀疑你不是故意的

#define CLIENT_FIFO_PREFIX = "./sgbd_client_"

也许应该是

#define CLIENT_FIFO_PREFIX "./sgbd_client_"

评论:当原型包含形式参数名称(除了强制类型)并且函数的定义使用不同的形式参数名称时,我偶尔会看到编译器的奇怪行为。IE。在您的pipes.c 中您的pipes.c 是否包含common.h?

此外,条件保护 #ifndef headerfilename #define headerfilename #endif 是一个很好的做法,但这与您的问题没有直接关系。

.PMCD。

于 2010-11-16T02:16:11.893 回答
0

我怀疑您可能有另一个名为 common.h 的文件被包含在内,而不是您期望的文件。我复制并粘贴了您的文件,它编译时没有任何警告。

于 2010-11-16T02:05:28.130 回答
0

您发布的文件中的包含看起来应该可以工作。一些想法还有什么可能是错的:

  • 是否common.hconsole.h尝试包含sgbd_server.h,以便您最终得到循环包含?
  • 您是否使用 include 警卫(甚至其他#ifdefs)并且可能将它们混合在某个地方,从而无意中排除了其中一个文件?
  • 您是否在common.h某处包含可能包含的路径而不是您想要的路径?
于 2010-11-16T02:06:03.950 回答