web-dev-qa-db-fra.com

Comment la structure de résultat de localtime est-elle allouée en C?

Je jouais avec le fichier time.h en C qui nous aide avec les fonctions heure/jour.

Je suis tombé sur:

struct tm * _Cdecl localtime(const time_t *__timer);

... qui semble renvoyer un pointeur sur tm struct. J'ai trouvé que return by address est principalement utilisé pour renvoyer de nouvelles allocations de mémoire.

Si tel est le cas, comment fonctionne le retour ci-dessus (l'adresse de retour d'un struct tm). L'objet retourné est-il défini quelque part?

Merci

36
Akash

Le pointeur renvoyé par localtime (et quelques autres fonctions) est en réalité un pointeur sur la mémoire allouée de manière statique. Vous n'avez donc pas besoin d'être libéré. De plus, vous ne devriez pas le libérer.

http://www.cplusplus.com/reference/clibrary/ctime/localtime/

Cette structure est allouée et partagée de manière statique par les fonctions gmtime et localtime. Chaque fois que l'une de ces fonctions est appelée, le contenu de cette structure est écrasé.

EDIT: Ajout de quelques éléments mentionnés dans les commentaires.

Un résultat direct de cette structure de données partagée est que localtime et des fonctions similaires ne sont pas thread-safe. La solution thread-safe varie selon les plates-formes. localtime_r pour POSIX et localtime_s pour MSVC .

42
Mysticial

Il renvoie un pointeur sur une partie de la mémoire allouée de manière statique (probablement une variable static définie dans localtime ou une variable globale définie quelque part dans la bibliothèque d'exécution C). Vous ne devez pas libérer une telle mémoire.

Évidemment, cette fonction n'est pas réentrante (mais peut être thread-safe si TLS est utilisé).

Vous devez faire attention lorsque vous utilisez ce pointeur: n'effectuez jamais d'appels de fonction pouvant appeler localtime/gmtime/... avant d'avoir fini d'utiliser ce pointeur, sinon le contenu de la mémoire référencée par votre pointeur pourrait changer (en réponse au nouvel appel). à localtime) et vous lirez des valeurs relatives à un autre time_t.

En général, la conception de la bibliothèque de date/heure est assez dépassée. Ce type d'optimisation valait la peine lorsque le langage C a été conçu. Aujourd'hui, cela ne donne que des problèmes.

Pour résoudre ces problèmes, il existe au moins deux versions améliorées différentes de ces fonctions: localtime_r (SUSv2, r reste pour "réentrant") et localtime_s (Microsoft, s reste pour "sûr"). Le triste fait en ce qui concerne la portabilité est qu’ils font presque la même chose (ils exigent que le struct tm de destination soit passé en tant que paramètre), mais diffèrent par le nom et l’ordre des paramètres.

11
Matteo Italia

La page de manuel dit:

La valeur de retour pointe vers une structure allouée de manière statique qui peut être remplacée par des appels ultérieurs à l'une des fonctions de date et d'heure.

Également:

La fonction localtime_r () fait la même chose, mais stocke les données dans une structure fournie par l'utilisateur. Il n'est pas nécessaire de définir tzname, timezone et daylight.

5
Kos

En fait, localtime renvoie généralement l'adresse d'un objet statique. Je soupçonne que cela ressemble à ceci:

struct tm *
localtime(const time_t *timer)
{
    static struct tm tm;

    /* Magic. */

    return &tm;
}
3
cnicutar

Ils renvoient un pointeur sur une structure statique locale de la bibliothèque. De la page de manuel:

NOTES 
 
 Les quatre fonctions asctime (), ctime (), gmtime () et localtime () renvoient 
 Un pointeur vers des données statiques et ne sont donc pas thread-safe. Les versions 
 Thread-safe asctime_r (), ctime_r (), gmtime_r () et localtime_r () sont spécifiées - 
 Par SUSv2 et disponibles depuis la libc 5.2.5. 
 
 POSIX.1-2001 dit: "Les fonctions asctime (), ctime (), gmtime () et localtime () 
 Doivent renvoyer des valeurs dans l’un des deux objets statiques: un broken- 
 une structure de temps d'arrêt et un tableau de type char. L'exécution de l'une des fonctions 
 peut écraser les informations renvoyées dans l'un de ces objets 
 par l'une des autres fonctions. " Cela peut se produire lors de la mise en œuvre de glibc 
.
3
Brian Roach

L'objet pointé renvoyé par la fonction localtime a une durée de stockage statique.

0
ouah