¿Cómo se asigna la estructura de resultado de localtime en C?

6 minutos de lectura

avatar de usuario
Akash

yo estaba jugando con el time.h archivo en C que nos ayuda con las funciones de hora/día.

Me encontré con:

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

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

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

Gracias

  • Usted define y asigna la estructura tm en tu código. localtime() almacena su salida en esa estructura y devuelve un puntero a esa misma estructura. Esto puede parecer redundante, pero a veces es útil para recuperar el puntero, aunque sepa dónde está la estructura.

    – Pete Wilson

    1 de enero de 2012 a las 17:37

  • @PeteWilson – Um, no, no lo haces. Por favor, vea las respuestas a continuación. Lo que describes es solo el caso en el _r versión de la llamada (localtime_r()) de SUSv2 o el _s versión de la llamada en MSVC

    -Brian Roach

    1 de enero de 2012 a las 17:44


  • posible duplicado de ¿Debe liberarse la estructura devuelta de localtime ()?

    – Vilhelm Grey

    26 de junio de 2013 a las 13:44

avatar de usuario
místico

El puntero devuelto por localtime (y algunas otras funciones) son en realidad punteros a la memoria asignada estáticamente. Por lo tanto, no necesita liberarlo, y no debe liberarlo.

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

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

EDITAR: Anexando algunas cosas mencionadas en los comentarios.

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

  • @OliCharlesworth en realidad tiene, lea (C99, 7.23.3 Funciones de conversión de tiempo) “Excepto por la función strftime, cada una de estas funciones devuelve un puntero a uno de los dos tipos de objetos estáticos […] La ejecución de cualquiera de las funciones que devuelven un puntero a uno de estos tipos de objetos puede sobrescribir la información en cualquier objeto del mismo tipo señalado por el valor devuelto por cualquier llamada anterior a cualquiera de ellos”.

    – ouah

    1 de enero de 2012 a las 17:29


  • También podría ser bueno señalar que debido a esto, no es seguro para subprocesos y el _r versiones de estas llamadas son.

    -Brian Roach

    1 de enero de 2012 a las 17:29

  • @BrianRoach Sí, ese es un muy buen punto. Curiosamente, no puedo encontrar el _r versiones fuera de las páginas man de linux. Tampoco aparece en MSVC. ¿Es una extensión del compilador?

    – Místico

    1 de enero de 2012 a las 17:33


  • @Místico – SUSv2; pubs.opengroup.org/onlinepubs/007908799/xsh/localtime.html . No hago Windows, así que no tengo idea de cuál es el equivalente o si existe.

    -Brian Roach

    1 de enero de 2012 a las 17:41


  • @Mysticial: para MSVC existe el equivalente _s versión (con parámetros intercambiados); los _r La versión no está en el estándar C, pero está definida en la especificación estándar de UNIX (las páginas del manual se refieren a SUSv2).

    – Mateo Italia

    1 de enero de 2012 a las 17:45

avatar de usuario
Mateo Italia

Devuelve un puntero a una parte de la memoria asignada estáticamente (probablemente un static variable definida dentro localtime o un global definido en algún lugar de la biblioteca de tiempo de ejecución de C). No debe liberar dicha 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 de función que pueda llamar localtime/gmtime/… antes de que termine de usar ese puntero, de lo contrario, el contenido de la memoria a la que hace referencia su puntero podría cambiar (en respuesta a la nueva llamada a localtime) y estarás leyendo valores relativos a otro time_t.

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

Para abordar estos problemas, existen al menos dos versiones mejoradas diferentes de estas funciones: localtime_r (SUSv2, r estancias para “reentrante”) y localtime_s (Microsoft, s se queda por “seguro”). El triste hecho de la portabilidad es que estos hacen casi lo mismo (requieren el destino struct tm para pasar como un parámetro), pero difieren en el nombre y el orden de los parámetros.

  • Nota: localtime_s() también se detalla en la especificación C11: sección normativa K.3.8.2.4. No estoy seguro si MS (o cualquiera) cumple con esa especificación C11.

    – chux – Reincorporar a Monica

    22 de julio de 2015 a las 15:19

  • Wow, que bueno que dijiste eso! Estaba haciendo exactamente eso: medir date_before y date_after y comparándolos. ¡Y ahora resulta que estaba comparando la misma variable! Confirmo que la dirección de impresión de date_before y date_after da el mismo valor.

    – Hola angel

    28 oct 2021 a las 11:41

los página man dice:

El valor devuelto apunta a una estructura asignada estáticamente que podría sobrescribirse con 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 diurna.

avatar de usuario
cnicutar

Realmente localtime normalmente devuelve la dirección de un objeto estático. Sospecho que se parece a esto:

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

    /* Magic. */

    return &tm;
}

avatar de usuario
Brian Cucaracha

Devuelven un puntero a una estructura estática local de la biblioteca. De la página del manual:

NOTES

The  four functions asctime(), ctime(), gmtime() and localtime() return
a pointer to static data and hence are  not  thread-safe.   Thread-safe
versions asctime_r(), ctime_r(), gmtime_r() and localtime_r() are spec‐
ified by SUSv2, and available since libc 5.2.5.

POSIX.1-2001 says: "The asctime(), ctime(), gmtime(),  and  localtime()
functions  shall  return values in one of two static objects: a broken-
down time structure and an array of type char.  Execution of any of the
functions  may  overwrite  the  information returned in either of these
objects by any of the other functions."  This can occur  in  the  glibc
implementation.

  • Las páginas de manual son una cosa maravillosa. En ese momento, SO no me mostraba que alguien más había respondido, así que pensé en publicar los documentos relevantes.

    -Brian Roach

    1 de enero de 2012 a las 17:50

avatar de usuario
ouah

El objeto puntiagudo que es devuelto por localtime La función tiene una duración de almacenamiento estática.

  • Las páginas de manual son una cosa maravillosa. En ese momento, SO no me mostraba que alguien más había respondido, así que pensé en publicar los documentos relevantes.

    -Brian Roach

    1 de enero de 2012 a las 17:50

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad