2010-11-16 5 views
1

Да, этот вопрос задавался много раз, и я смотрел и читал форумы и сообщения SO, но ответы все не связаны (или, как они кажутся) с этим. Итак, у меня есть главный файл: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); 
} 

Затем файлы заголовков:

- 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_open и pipe_close определены в pipe.c и в основном возвращаются 0 и 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 и реализует некоторые функции управление вводом/выводом на консоли, ничего необычного. Как вы видите, он также компилируется отдельно.

Теперь, когда я печатаю 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’ 

Я бег GCC на amd64 Linux, если это имеет значение (я сомневаюсь).

Теперь, почему это предупредило меня об этом? Две функции объявлены в common.h, который включен в sgbd_server.h ... Что мне здесь не хватает?

Благодарим вас за внимание!

** UPDATE **

Спасибо всем за ваше предложение. Я попытался найти, будет ли файл common.h где-то еще в моем включенном пути, который будет включен каким-то образом ... Хотя я не смог найти ни одного, который мог бы ускользнуть в процессе компиляции вместо локального common.h (sig) Я нашел несколько файлов .ghc, сидящих в моей исходной папке. Так как они не очищены make clean, я вручную удалил эти файлы. Угадай, что? Нет предупреждения. Что это за файлы и почему они созданы?

+0

Помогает ли это '#inclde" common.h "' в sgbd_server.c? – vpit3833

+0

Я не вижу никаких причин для этого. Как выглядит sgbd_client.c? –

+1

Попробуйте использовать 'gcc -E sgbd_server.c', чтобы увидеть, что именно компилируется после завершения препроцессора. – caf

ответ

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.


На основе вашего редактирования:

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 была опечатка, и вы имели в виду 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, чтобы гарантировать, что в серверной программе был использован новый предварительно скомпилированный заголовочный файл.

Если вы хотите отследить его до первопричины и получить правильное объяснение, это вопрос вкуса - есть школа мысли, что вы должны иногда просто записывать, как вы ее исправили, и не слишком беспокоиться, чтобы вы не стали запутался в самой природе самой реальности.

Не мне, конечно, я тип личности, который будет пытаться отслеживать мои проблемы назад к индивидуальной податомной частице, вызвавшей ее, но иногда прагматизм требует от меня, чтобы отпустить :-)

+0

Я удалил все ссылки 'common.h' в make-файле (они не были изначально присутствовали при появлении предупреждения). Однако директива '# error' не изменяет ничего, что означает, что компилятор фактически не включает файл' common.h' в исходном тексте прямо на всех! –

+0

, когда я помещаю '#include" common.h "' непосредственно в 'sgbd_server.c', предупреждение исчезает, но я получаю сообщение об ошибке: redefinition 'struct Info_FIFO_Transaction''. Ошибки переопределения O_o –

+0

могут быть устранены с помощью условных охранников, о которых говорили ваши респонденты. –

0

Я подозреваю, что у вас может быть другой файл с именем common.h, который включается вместо ожидаемого файла. Я копирую и вставляю ваши файлы и скомпилирован без предупреждения.

+0

нет другого common.h в текущей работе непосредственно там, где все файлы .... если нет одного 'common.h', что я не знаю ... –

+0

Может быть что-то в/usr/include или другой каталог по умолчанию включен. Попробуйте директиву #error, предложенную paxdiablo. Это докажет, что он получает файл из локального каталога. – JOTN

+0

, когда я включаю 'common.h' в' sgbd_server.c', похоже, все это записывает, но когда он включен в 'sgbd_server.h', тогда он не включен ... это довольно странно. Тем не менее, я переименовал 'common.h', и такое же поведение по-прежнему сохраняется. –

0

Вложения в файлы, которые вы опубликовали, выглядят так, как будто они должны работать. Несколько идей, что еще может быть неправильно:

  • ли common.h или console.h попытка включить sgbd_server.h, так что вы в конечном итоге с круговой включает в себя?
  • Вы используете блокировку (или даже другие #ifdef) и, возможно, смешали их где-нибудь, чтобы один из файлов был исключен непреднамеренно?
  • У вас есть еще common.h где-то в вас есть путь, который может быть включен вместо того, который вы намеревались?
+0

nope. Вот почему я спрашиваю здесь, это точно все файлы, которые скомпилированы ... у вас есть весь исходный код до сих пор (начался сегодня); то, что вы видите, это то, что компилируется. –

1

наблюдения: у вас есть = в виде #define, который я подозреваю, вы не значит иметь там

 
#define CLIENT_FIFO_PREFIX = "./sgbd_client_" 

должно быть возможно

 
#define CLIENT_FIFO_PREFIX "./sgbd_client_" 

комментарии: Я иногда было замечено странное поведение компиляторов, когда прототип содержит формальные имена параметров (в дополнение к обязательным типам), а в определении функции используются разные формальные имена параметров. то есть. в ваших pipe.c Вы используете pipe.c common.h?

Кроме того, условные охранники #ifndef headerfilename #define headerfilename #endif является хорошей практикой, но это не имеет прямое отношение к вашей проблеме.

. PMCD.

+0

спасибо, что заметили знак =. :) –