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_openpipe_closeで定義されている2 つの関数は、基本的にとpipe.cを返します。この最後のファイルは、Make ファイルで個別にコンパイルされます。0void

私は 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を実行しています(疑わしい)。

さて、なぜそれについて私に警告するのでしょうか? 2 つの関数は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 ファイルとしてコンパイルしようとコンパイラに指示しているようです。これは、クライアントとサーバーのコンパイル コマンドの違いの 1 つであり、修正する必要があります。

他に私が提案できる唯一のことは、取得していると思われるヘッダー ファイルを取得していない可能性があるということです。次の行を入力することから始めます。

#error Urk! in common.h

あなたの一番上にあり、common.hそこでビルドが失敗することを確認してください。

そうでない場合、そのファイルは別の場所から来ています。sgbd_server.hファイルでも同じことをしたいかもしれません。


あなたの編集に基づいて:

ソース フォルダに .ghc ファイルがいくつかあります。これらは make clean でクリーンアップされていないため、手動で削除しました。何だと思う?警告なし。これらのファイルとは何ですか?なぜ作成されるのですか?

これらは、ghcがタイプミスであり、少なくとも部分的にコンパイル プロセスを高速化するために、gchによって生成されたプリコンパイル済みヘッダーであると仮定します。gccビルド中にヘッダー ファイルを何度も処理する必要がなく (ヘッダー ファイルを含むソース ファイルごとに 1 回)、ヘッダー ファイルを 1 回プリコンパイルして、プリコンパイル済みバージョンを使用する方がはるかに効率的です。

common.hこれは、サーバーを実行したときにコンパイラのコマンドラインに含めたことが原因である可能性が最も高いと思います。デフォルトでは、 に直接指定さgccれたヘッダー ファイルはプリコンパイル済みヘッダー ファイルに変換され、その後優先的に使用されます。これをテストするために、qq.hファイルを作成して実行gcc qq.hし、 popped を出力しました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_"

コメント: プロトタイプに (必須の型に加えて) 仮パラメーター名が含まれていて、関数の定義が異なる仮パラメーター名を使用している場合、コンパイラーの奇妙な動作を時々目撃しました。すなわち。あなたの 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.h、またはconsole.hインクルードしようとしますか?sgbd_server.h
  • インクルード ガード (または他#ifdefの s) を使用していて、ファイルの 1 つが意図せずに除外されるように、それらをどこかで混同していませんか?
  • common.hインクルード パスのどこかに、意図したパスの代わりに含まれる可能性のある別のパスがありますか?
于 2010-11-16T02:06:03.950 に答える