web-dev-qa-db-fra.com

déclaration implicite de fonction usleep

gcc (GCC) 4.6.3
c89

J'essaie d'utiliser usleep. Cependant, je reçois toujours l'avertissement suivant:

déclaration implicite de fonction usleep

J'ai inclus le unistd.h En tête de fichier.

Les pages de manuel mentionnent quelque chose à ce sujet. Mais je ne suis pas sûr de comprendre cela:

usleep():
   Since glibc 2.12:
       _BSD_SOURCE ||
           (_XOPEN_SOURCE >= 500 ||
               _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) &&
           !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
   Before glibc 2.12:
       _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED

Mais vous ne savez pas ce que je dois faire avec ce qui précède?

23
ant2009

Cette liste est les conditions préalables pour avoir usleep défini. Il s'agit essentiellement d'une expression de type C impliquant #define variables qui doivent être vraies avant d'inclure le fichier d'en-tête.

Le fichier d'en-tête lui-même ne définira que usleep à l'intérieur de ce qui est généralement un nid massif de #ifdef déclarations et les développeurs ont pris le temps de vous dire ce que vous devez faire pour que vous n'ayez pas à passer des heures à essayer de le découvrir vous-même :-)

En supposant que vous utilisez un glibc 2.12 ou mieux, cela signifie que vous devez soit:

  • declare _BSD_SOURCE; ou
  • déclarer une combinaison compliquée de trois autres choses, que je ne prendrai pas la peine de décoder.

La solution la plus simple consiste probablement à compiler simplement avec gcc -D _BSD_SOURCE ou mettez:

#define _BSD_SOURCE

dans le code avant d'inclure le fichier d'en-tête qui vous donne usleep.

Vous voudrez probablement les définir avant tout inclut au cas où il y aurait des dépendances entre les différents fichiers d'en-tête.

28
paxdiablo

Cela peut fonctionner: Ajouter -std=gnu99 lors de la compilation avec gcc sous Linux.

Exemple:

arm-linux-gcc -lpthread -std=gnu99  -o test ArmLinuxDataPipe1.2.1.c
19
ioilala

Tl; dr

Si vous devez obtenir du code hérité qui utilise usleep() pour compiler, ajoutez ces lignes à un fichier d'en-tête que vous incluez avant toute autre bibliothèque:

#define _XOPEN_SOURCE   600
#define _POSIX_C_SOURCE 200112L

Ou ajoutez les drapeaux du compilateur -std=c11 -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L À votre makefile.

Cela indique à l'environnement que votre programme utilise cette ancienne version de l'API UNIX , dans laquelle usleep() n'était pas obsolète.

Alternativement - et s'il s'agit d'un nouveau code, certainement - remplacez usleep() par nanosleep() , définissez les macros de test de fonctionnalité en fonction de votre version de la bibliothèque, et examinez votre base de code pour d'autres pourritures de bits.

Sous Linux, vous pouvez vérifier quelles valeurs de _XOPEN_SOURCE Et _POSIX_C_SOURCE Votre bibliothèque prend en charge dans man feature_test_macros.

L'image complète

Réponse plus longue: voici ce qui se passe.

Historiquement, il existait plusieurs normes UNIX différentes, et la meilleure pratique éventuelle à laquelle tout le monde a eu recours était de demander au code de spécifier la version de l'API UNIX pour laquelle il a été écrit. Les programmeurs l'ont fait en définissant une macro de test de fonctionnalités.

L'une des premières divisions dans UNIX a été entre le système V d'AT & T et la distribution standard Berkeley (BSD) de l'Université de Californie. Étant donné que System V était la version officielle et que son comportement est devenu celui par défaut, alors que BSD Unix était l'un des premiers logiciels gratuits et utilisé dans de nombreuses universités, il est beaucoup plus courant de voir le code hérité déclarer _BSD_SOURCE Que _SVID_SOURCE. La macro _BSD_SOURCE Essaie notamment d'activer des extensions à partir d'une grande variété de systèmes d'exploitation différents sur une période de plus de quarante ans. Parfois, il est même utilisé comme fourre-tout pour les extensions non standard. Les deux macros sont obsolètes et contrairement à la réponse actuellement acceptée, vous ne devez jamais utiliser l'une ou l'autre dans le nouveau code.

Au cours de ce siècle, il y avait deux normes UNIX, POSIX, qui est devenue une norme IEEE, et la spécification Single Unix (SUS) du groupe Open (X/Open). Le X/Open SUS est un sur-ensemble de POSIX et ce que vous écririez normalement. Il existait auparavant un certain nombre de macros de test de fonctionnalités que vous pouviez déclarer pour activer les versions alors actuelles de ces normes, et celles-ci sont toujours prises en charge pour la compatibilité descendante. Vous pouvez en voir certaines dans le conditionnel que vous avez collé, mais vous n'avez pas à vous en préoccuper lorsque vous écrivez du nouveau code. Une macro qui vérifie le code, _XOPEN_SOURCE_EXTENDED, est désormais obsolète, mais a historiquement sélectionné une version du SUS de 1995.

En théorie, la macro de test de fonctionnalités correcte à définir sur n'importe quelle version moderne d'UNIX ou Linux est _XOPEN_SOURCE. Vous devez rechercher le numéro de version le plus récent pris en charge par votre bibliothèque. En pratique, je pense qu'il est prudent de coder défensivement pour définir également _POSIX_C_SOURCE, Afin de garantir que personne d'autre ne peut le définir de manière incohérente et casser votre code. Votre question est un bon exemple: si vous définissez _XOPEN_SOURCE Pour la compatibilité descendante, mais que _POSIX_C_SOURCE Est défini sur une version plus récente ailleurs dans votre chaîne d'outils, la version supérieure de _POSIX_C_SOURCE aura priorité et usleep() ne fonctionnera pas.

Donc, ce que ces conditions signifient, c'est que usleep() n'était pas une fonction POSIX, mais était à un moment présent sur certains systèmes d'exploitation de type BSD, et en a donc fait le SUS en 1995. Il a été déconseillé en 2008, et la sélection de n'importe quelle version de POSIX ou le SUS depuis lors le désactive activement. Par conséquent, il est activé si vous sélectionnez la version 500 ou 600 du SUS (et un autre synonyme obsolète l'allume également), mais déconseillé si vous sélectionnez une version récente de POSIX ou du SUS. Ils sont également activés si vous sélectionnez l'option quoi que ce soit, mais c'est une mauvaise idée.

2
Davislor

Ajoutez ce qui suit en haut de votre code:

// For `nanosleep()`:
#include <time.h>

#define __USE_POSIX199309
#define _POSIX_C_SOURCE 199309L

Et puis utilisez nanosleep() à la place, pour créer votre propre fonction sleep_us() pour dormir un nombre défini de microsecondes:

void sleep_us(unsigned long microseconds)
{
    struct timespec ts;
    ts.tv_sec = microseconds / 1e6;             // whole seconds
    ts.tv_nsec = (microseconds % 1e6) * 1e3;    // remainder, in nanoseconds
    nanosleep(&ts, NULL);
}

Pour la compilation et l'exécution sur Linux Ubuntu, j'ai créé un fichier sleep_test.c et utilisé:

gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_test

Les références:

  1. (Ceci est intentionnellement une référence circulaire: voir mes commentaires sous cette réponse): Y a-t-il une fonction de sommeil alternative en C à millisecondes?
  2. http://man7.org/linux/man-pages/man2/nanosleep.2.html
1
Gabriel Staples

L'utilisation de nanosleep () a plutôt fonctionné pour moi.

Sur une note pertinente: usleep () a été supprimé depuis POSIX-2008 et recommande d'utiliser nanosleep () à la place.

1
electron1979