Mi función c usando difftime devuelve 65535 a veces

Tengo una función que utiliza difftime para detectar el tiempo en segundos desde que se detuvo el latido del corazón de la comunicación. Esta función podría ejecutarse tan rápido como cada 50 milisegundos. La función parece funcionar, excepto que de vez en cuando devuelve 65535. Puedo reducir la ejecución a una vez por segundo, ya que el retorno de difftime es solo en segundos. Pero no sé si va a solucionar el problema. ¿Es el problema porque no estoy lanzando correctamente el retorno de difftime a uint16_t desde el doble?

Este progtwig se ejecuta en una máquina de ubuntu 64bit.

Por favor ayuda. Gracias.

uint16_t commlost(uint16_t heartbeat_read_cur) { time_t current_time; static time_t previous_time; static uint16_t commlost_secs_cur = 0; static uint16_t commlost_secs_prev = 0; static uint16_t heartbeat_read_prev = 0; static bool first_time = TRUE; if (first_time) { previous_time = time(NULL); first_time = FALSE; } time(&current_time); commlost_secs_prev = commlost_secs_cur; if(heartbeat_read_prev == heartbeat_read_cur) { commlost_secs_cur += difftime(current_time, previous_time); } else { heartbeat_read_prev = heartbeat_read_cur; commlost_secs_cur = 0; } previous_time = current_time; return (commlost_secs_cur); } 

difftime() se usa en sistemas donde time_t admite el tiempo a una resolución más alta que los segundos integrales. Aunque permitido, nunca he encontrado un sistema así, no creo que exista uno. Específicamente en los sistemas POSIX, time_t se mide en segundos integrales, y difftime() es equivalente a la resta aritmética de sus argumentos, por lo que en realidad es mejor utilizar simplemente:

 commlost_secs_cur += current_time - previous_time ; 

Dicho esto, su implementación es algo demasiado compleja, en lugar de acumular tiempo desde la llamada anterior, que puede ser más pequeña que la resolución del reloj, simplemente puede marcar el último latido del corazón observado y devolver el tiempo desde entonces:

 int commlost(uint16_t heartbeat_read_cur) { time_t current_time = time(0) ; static time_t heartbeat_timestamp = 0 ; static uint16_t heartbeat_read_prev ; // If first time, or heartbeat changed... if( heartbeat_timestamp == 0 || heartbeat_read_prev != heartbeat_read_cur) { // ... timestamp heartbeat heartbeat_timestamp = time(0) ; // ... keep last heartbeat heartbeat_read_prev = heartbeat_read_cur ; } // Return seconds since last heartbeat timestamp return current_time - heartbeat_timestamp ; } 

No estoy seguro de por qué usaría uint16_t para esto; hay poca o ninguna ventaja a menos que sea por compatibilidad con algún protocolo o formato de archivo específico.

Antes de consultar la hora, lea la página del manual de time (7) (y léala de nuevo).

Sugiero que use clock_gettime (2) con, por ejemplo, CLOCK_MONOTONIC o CLOCK_REALTIME , y preferiblemente use el double para los cálculos de tiempo (ya que una struct timespec es generalmente más grande que cualquier tipo integral).

No use uint16_t para tales cálculos de tiempo.

Intenta usar

 inline double double_gettime (clockid_t cid) { struct timespec ts = {0,0}; clock_gettime(cid, &ts); return (double)ts.tv_sec + 1.0e-9*ts.tv_nsec; } 

¡Es posible que desee hacer esa función más sofisticada, probando si clock_gettime está fallando y dando NAN cuando falla! Esto se deja como un ejercicio para el lector. También puede, para CLOCK_REALTIME , etc., medir la diferencia entre algún momento al inicio del proceso y el tiempo actual (es decir, calcular una struct timespec de las diferencias de tiempo y convertir esa diferencia a un double )

Entonces cosas como

 double tstart = double_gettime(CLOCK_REALTIME); some_long_computation(); double tend = double_gettime(CLOCK_REALTIME); printf ("needed %f seconds to compute\n", tend-tstart); 

Ver también reloj (3).