¿Cómo se asigna la estructura del resultado del tiempo local en C?

Estaba jugando con el archivo time.h en C que nos ayuda con las funciones de tiempo / día.

Me encontré con:

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

… que parece devolver un puntero a tm struct. Descubrí que la dirección de devolución se usa principalmente para devolver nuevas asignaciones de memoria.

Si esto es así, ¿cómo funciona realmente el retorno anterior (la dirección de retorno de una struct tm ). ¿El objeto devuelto está definido en alguna parte?

Gracias

El puntero devuelto por localtime (y algunas otras funciones) son en realidad punteros a la memoria asignada estáticamente. Entonces no necesitas liberarte. Además, no deberías liberarlo.

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

Esta estructura está asignada y compartida estáticamente por las funciones gmtime y localtime. Cada vez que se llama una de estas funciones, se sobrescribe el contenido de esta estructura.

EDITAR: Agregar algunas cosas mencionadas en los comentarios.

Un resultado directo de esta estructura de datos compartida es que el tiempo localtime y las funciones similares no son seguras para subprocesos. La solución de seguridad de subprocesos varía según las diferentes plataformas. localtime_r para POSIX y localtime_s para MSVC .

Devuelve un puntero a una parte de la memoria estáticamente asignada (probablemente una variable static definida dentro de localtime o una global definida en algún lugar de la biblioteca C runtime). No debes liberar tal memoria.

Obviamente, esta función no es reentrante (pero puede ser segura para subprocesos si se usa TLS).

Debe tener cuidado al usar este puntero: nunca haga ninguna llamada a funciones que pueda llamar a gmtime / gmtime / … antes de que termine de usar ese puntero; de lo contrario, el contenido de la memoria a la que hace referencia el puntero podría cambiar (en respuesta a la nueva llamada) a localtime ) y leerá valores relativos a otro time_t .

En general, el diseño de la biblioteca de fecha / hora está bastante desactualizado, este tipo de optimización valía la pena cuando se diseñó el lenguaje C, hoy en día solo da problemas.

Para solucionar estos problemas hay al menos dos versiones mejoradas diferentes de estas funciones: localtime_r (SUSv2, r permanece para “reentrant”) y localtime_s (Microsoft, s permanece como “seguro”). La triste realidad de la portabilidad es que hacen casi lo mismo (requieren que la struct tm destino se pase como un parámetro), pero difieren en el nombre y el orden de los parámetros.

La página man dice:

El valor de retorno apunta a una estructura estáticamente asignada que puede ser sobrescrita por llamadas posteriores a cualquiera de las funciones de fecha y hora.

También:

La función localtime_r () hace lo mismo, pero almacena los datos en una estructura proporcionada por el usuario. No es necesario establecer tzname, zona horaria y luz del día.

En realidad, localtime generalmente devuelve la dirección de un objeto estático. Sospecho que se ve así:

 struct tm * localtime(const time_t *timer) { static struct tm tm; /* Magic. */ return &tm; } 

Devuelven un puntero a una estructura estática local a la biblioteca. Desde la página man:

  NOTAS

 Las cuatro funciones asctime (), ctime (), gmtime () y localtime () regresan
 un puntero a datos estáticos y, por lo tanto, no son seguros para subprocesos.  A salvo de amenazas
 las versiones asctime_r (), ctime_r (), gmtime_r () y localtime_r () son
 ified por SUSv2, y disponible desde libc 5.2.5.

 POSIX.1-2001 dice: "The asctime (), ctime (), gmtime () y localtime ()
 las funciones devolverán valores en uno de dos objetos estáticos: un
 estructura de tiempo de inactividad y una matriz de tipo char.  Ejecución de cualquiera de los
 las funciones pueden sobrescribir la información devuelta en cualquiera de estos
 objetos por cualquiera de las otras funciones. "Esto puede ocurrir en el glibc
 implementación. 

El objeto puntiagudo que devuelve la función localtime tiene una duración de almacenamiento estática.