mktime и localtime вызывают ошибку сегментации, как правильно инициализировать?

У меня есть следующая функция, которая неоднократно вызывается в более крупной программе:

double troublesome_function() {
time_t time_ini = time(NULL);
struct tm tm_ini = *localtime(&time_ini);

(...)

time_t secs_passed;  
secs_passed = mktime(&tm_ini);

double return_value =0;

return_value = (double)secs_passed;

return(return_value); 
}

В большинстве случаев он работает просто отлично. Но в некоторых случаях строка *localtime(&time_ini) вызывает ошибку сегментации. Удаление этой инициализации из tm_ini выглядит нормально, но тогда код снова будет работать нормально в большинстве случаев, но строка mktime(&tm_ini) вызовет ошибку сегментации. Наконец, операция возврата также может быть ошибочной, что я проверил, добавив в код printfs.

Согласно этому ответу "Одна ошибка с localtime заключается в том, что возвращаемый указатель является указателем на статическую глобальную переменную и последующие вызовы для localtime обновления переменной."

Я подозреваю, что повторные вызовы mktime вызывают такое поведение, поэтому при добавлении переменной статического счетчика это происходит на 94-м вызове.

Есть ли способ предотвратить эти помехи для функций из time.h?


person Mefitico    schedule 19.06.2019    source источник
comment
Обратите внимание, что localtime может завершиться ошибкой и вернуть нулевой указатель. Подумайте о том, что происходит, когда вы разыменовываете нулевой указатель.   -  person Some programmer dude    schedule 19.06.2019
comment
Насколько я понимаю, у вас есть проблема, если вы вызываете функцию из разных потоков, поэтому у вас есть состояние гонки. Предложения: вы можете использовать localtime_r, если вы работаете с posix, и localtime_s, если вы работаете с окнами. Вы можете использовать #ifdef, чтобы условно включить их и обернуть их все в функцию, чтобы обеспечить несколько переносимую альтернативу. Внимание: для двух функций требуются одни и те же входы, но поменянные местами. Предостережение 2: похоже, что C11 имеет localtime_s (называемый Windows), но с порядком ввода localtime_r .   -  person CuriouslyRecurringThoughts    schedule 19.06.2019
comment
@CuriosityRecurringThoughts: мне нужно реализовать решение как для Windows, так и для Linux, поэтому спасибо за указание как localtime_r, так и localtime_s. Тем не менее, это, кажется, решает проблему с localtime, но после изменения я все еще получаю проблему с mktime.   -  person Mefitico    schedule 19.06.2019
comment
@Mefitico тогда, скорее всего, так, как говорит какой-то чувак-программист: локальное время возвращает NULL, вы можете добавить проверку, чтобы подтвердить идею.   -  person CuriouslyRecurringThoughts    schedule 19.06.2019
comment
localtime_s добавлен в C11, поэтому он должен работать и в Linux, или в любом компиляторе C11.   -  person KamilCuk    schedule 20.06.2019