warning: implicit declaration of function ‘kill’ [РЕШЕНО]

Добрый день!

Не знаю даже, где задать вопрос такой? Все, к кому обращался, не знают ответа.

Пишу код на Си (стандарт: ANSI C99 (ISO/IEC 9899:1999)) под Linux, но так же нужно чтобы он запускался и под BSD, QNX и другие POSIX-совместимые системы.
Вот кусок Makefile:

OUTPUT = engine
LANGUAGE = -std=c99
OBJ = ./obj/
BIN = ./bin/
SRC = ./src/
LIB = 
INCLUDES = 
# For release
#OPTIMIZATION = -O3
# For debug
OPTIMIZATION = -O0 -g
WARNINGLEVEL = -Wall

CC = gcc
CFLAGS += $(WARNINGLEVEL)
CFLAGS += $(OPTIMIZATION)
CFLAGS += $(LIB)
CFLAGS += $(LANGUAGE)

Далее таргеты

Т.е. видите, что я использую -std=c99.

Вот кусок кода в файле main.c:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <signal.h>

Далее идёт код

И на строке 457 вызывается функция kill

Обратите внимание на то, что файлы <sys/types.h>, <signal.h> подключены вначале файла, и <sys/types.h> включён раньше <signal.h> (если это имеет значение).

При компиляции, компилятор ругается:

./src/main.c:457: warning: implicit declaration of function ‘kill’

Т.е. он не видит kill, при этом исполняемый elf-файл собирается.
При запуске исполняемого файла kill отрабатывает нормально.

Читаем man:

$ man 2 kill

KILL(2)                                Linux Programmer's Manual                               KILL(2)

NAME
       kill - send signal to a process

SYNOPSIS
       #include <sys/types.h>
       #include <signal.h>

       int kill(pid_t pid, int sig);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       kill(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE

Как видно, требуется подключение двух заголовочных файлов: <sys/types.h> и <signal.h>. В файле main.c, где вызывается kill, они подключены.
Но не работает! Компилятор ругается. Хотя всё линкуется и исполняется вполне корректно.

Теперь давайте посмотрим код в файле signal.h:

/* Send signal SIG to process number PID.  If PID is zero,
   send SIG to all processes in the current process's process group.
   If PID is < -1, send SIG to all processes in process group - PID.  */
#ifdef __USE_POSIX
extern int kill (__pid_t __pid, int __sig) __THROW;
#endif /* Use POSIX.  */

Объявление находится под ifdef __USE_POSIX. Пробовал в файле main.c писать так:

#ifdef __USE_POSIX
	printf("\n\nPOSIX USE\n\n");
#else
	printf("\n\nPOSIX NOT USE\n\n");
#endif

Выводит: POSIX NOT USE

В чём же дело?

Хидеры проекта покажи :)

Хидеры проекта покажи :)
и посмотри что генерит cpp

Compute:
Bosch M2.8.1 -> custom Bosch M2.8.3 clone from Russia.
Speed about 260 km,Ram 2 pers.,HDD - 70 kg,210 FLOPS ;)

slepnoga написал(а): Хидеры

slepnoga написал(а):
Хидеры проекта покажи :)

Не понял. Какие хедеры? Я же показал вроде:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <signal.h>
slepnoga написал(а):
и посмотри что генерит cpp

Можно поподробнее? Какой cpp?

не понял. Какие хедеры? Я же

не понял. Какие хедеры? Я же показал вроде:

У тебя весь проект состоит из 1-го файла ?

Можно поподробнее? Какой cpp?
DESCRIPTION
       The C preprocessor, often known as cpp, is a macro processor that is used automatically by the C compiler to transform your program before compilation.  It is called a macro processor
       because it allows you to define macros, which are brief abbreviations for longer constructs.

       The C preprocessor is intended to be used only with C, C++, and Objective-C source code.  In the past, it has been abused as a general text processor.  It will choke on input which
       does not obey C's lexical rules.  For example, apostrophes will be interpreted as the beginning of character constants, and cause errors.  Also, you cannot rely on it preserving
       characteristics of the input which are not significant to C-family languages.  If a Makefile is preprocessed, all the hard tabs will be removed, and the Makefile will not work.

       Having said that, you can often get away with using cpp on things which are not C.  Other Algol-ish programming languages are often safe (Pascal, Ada, etc.) So is assembly, with
       caution.  -traditional-cpp mode preserves more white space, and is otherwise more permissive.  Many of the problems can be avoided by writing C or C++ style comments instead of native

Compute:
Bosch M2.8.1 -> custom Bosch M2.8.3 clone from Russia.
Speed about 260 km,Ram 2 pers.,HDD - 70 kg,210 FLOPS ;)

Да какая разница какие хедеры

Да какая разница какие хедеры в других файлах?

В общем, разобрался! Всем спасибо!

Дополнительно

Хотелось бы добавить вот что:
когда вместо -std=c99 ставлю -std=gnu99, то ошибок не возникает, всё компилируется и линкуется без предупреждений.

При этом, если я использую -std=c99 у меня ругается на kill, но на open, read, write, fork, setsid, chdir, sysconf, unlink и другие функции, не входящие в стандарт ANSI C99, но входящие в стандарт POSIX не ругается и воспринимает их без предупреждений.

Кто-то может как-то прокомментировать эту ситуацию?

Возможно это связано с тем, что signal.h входит в стандарт ANSI C99 и ANSI C89, но в них не определена функция kill. А если мы используем стандарт GNU, то в этих файлах есть kill. Как вы думаете?

Надеюсь поможет

Судя по

# grep _USE_POSIX /usr/include/features.h

это как-то завязано на спецификацию IEEE Std 1003.1...
UPD
А, это и есть спецификация POSIX
http://ru.wikipedia.org/wiki/POSIX
UPD2
Короче говоря, функция kill входит состав POSIX
А зачем, собственно -std=c99?

eegorov написал(а): Судя по

eegorov написал(а):
Судя по

# grep _USE_POSIX /usr/include/features.h

это как-то завязано на спецификацию IEEE Std 1003.1...
UPD
А, это и есть спецификация POSIX
http://ru.wikipedia.org/wiki/POSIX
UPD2
Короче говоря, функция kill входит состав POSIX
А зачем, собственно -std=c99?

Ну что она (функция kill) входит в стандарт POSIX и другие стандарты (я уже написал в посте "Предположение") это понятно, конечно. Просто у меня то была проблема такая: функция, например, fork так же входит в стандарты POSIX и другие (SVr4, 4.3BSD, POSIX.1-2001), но на неё компилятор не ругается. А на kill ругается. Но теперь я понял почему.
В общем, всё дело в том, что она объявлена в одном и том же заголовочном файле, который описан в стандарте ANSI C.

eegorov написал(а):
А зачем, собственно -std=c99?

В смысле зачем? Для указания стандарта, который использую.

Предположение

Пока писал и изучал проблему, додумался.

В общем так. Открываем стандарт: ISO/IEC 9899:1999 (WG14/N1124 Committee Draft - May 6, 2005 ISO/IEC 9899:TC2). Извините, уж что нашёл.
Читаем его. Параграф 7 определяет библиотеки, входящие в стандарт. Раздел 7.14 описывает что в стандарт входит библиотека для работы с сигналами, заголовочный файл которой signal.h.
Смотрим что входит в этот заголовочный файл: типы, макросы, функции.

Вот цитата из стандарта:

Цитата:
The header <signal.h> declares a type and two functions and defines several macros,
for handling various signals (conditions that may be reported during program execution).

Функции всего две:

void (*signal(int sig, void (*func)(int)))(int);
int raise(int sig);

Функция kill не входит в стандарт ISO/IEC 9899:1999.

Но в Linux (и других POSIX-совместимых заголовочных файлах) она определена так же в файле signal.h. Но под #ifdef:

/* Send signal SIG to process number PID.  If PID is zero,
   send SIG to all processes in the current process's process group.
   If PID is < -1, send SIG to all processes in process group - PID.  */
#ifdef __USE_POSIX
extern int kill (__pid_t __pid, int __sig) __THROW;
#endif /* Use POSIX.  */

Т.е. функция kill находится в расширении стандарта, но не входит в сам стандарт ISO/IEC 9899:1999. Даже не так - функция kill определена в стандартах: SVr4, 4.3BSD, POSIX.1-2001 (man 2 kill). При этом она определена в том же файле signal.h, а не в отдельном файле. И когда в опции компилятора gcc ставится -std=gnu99, определяются несколько новых define и включается kill. А функции fork, read, write, sysconf, chdir и т.д. определены в отдельных файлах, поэтому опция компилятора -std=gnu99 или -std=c99 никак не влияет на это.

В общем, причина понятна. Просто надо включить расширение -std=gnu99 и тогда компиляция проходит без ошибок!

Просто надо включить

Просто надо включить расширение -std=gnu99 

мдя, а просил -std=std99

extern int kill (__pid_t __pid, int __sig) __THROW;

насколько мне подсказывает мои старый маразматический моск int __sig есть __номер__ сигнала.
т.е для -std=std99 туда надо тупо обертку с int __sig == 9 - вот вам и kill.

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

Compute:
Bosch M2.8.1 -> custom Bosch M2.8.3 clone from Russia.
Speed about 260 km,Ram 2 pers.,HDD - 70 kg,210 FLOPS ;)

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".