ctime_r не удалось в докере - PullRequest
       33

ctime_r не удалось в докере

0 голосов
/ 31 августа 2018

У меня есть приложение в Docker, которое является многопоточным. И мой код для передачи времени, как показано ниже.

FILE *fp = NULL;
char buf[256] = {0};
char filename[64] = {0};
long timestamp;
char status[16] = {0};
char tbuf[26] = {0};


fp = popen(cmd, "r");
if (fp) {
    while (fscanf(fp, "%s %d %s", filename, &timestamp, status) != EOF) {
        char *ts = ctime_r(&timestamp, tbuf);
        if (ts) {
            ts[strlen(ts)-1] = '\0';
            sprintf(buf, "%-32s%-32s%-8s", filename, ts, status);
        } else {
            sprintf(buf, "%-32s%-32s%-8s", filename, "Miss", status);
        }
    }
    pclose(fp);
}

Но содержимое tbuf выглядит как "Сб 29 октября 21:37:05 44614", а ts равно NULL.

Я думаю, что отметка времени является допустимым значением. Но почему это не удалось?

1 Ответ

0 голосов
/ 31 августа 2018

почему это не удалось?

OP позже добавил код и сообщил "error of ... fscanf" .

С включенными предупреждениями мой компилятор также предупреждал.

предупреждение: формат "% d" ожидает аргумент типа "int *", но аргумент 4 имеет тип "long int *"


Читать time_t из текстового файла сложно. Атрибуты диапазона, эпохи, типа данных - все в игре. Кроме того, как текстовые данные в файле, атрибуты могут отличаться от системы, в которой они были записаны. Обратите внимание, что для time_t.

нет спецификатора fscanf().

Пока давайте предположим, что текстовая метка времени является просто числовой и соответствует целому числу time_t, хотя мы не знаем специфику целочисленного типа. Более продвинутые методы не требуют этих допущений.

Считайте отметку времени, используя самый широкий доступный тип со знаком, например intmax_t (или long в системах до C99). Некоторая проверка диапазона стоит усилий. Я также рекомендовал бы писать time_t, используя тот же широкий тип.

Примечание: лучше сравнить fscanf() возвращаемое значение с одним ожидаемым значением (3), а не только с одним из различных неожиданных значений (EOF, 0, 1, 2). Используйте ограничения ширины для ввода строки.

char filename[64] = {0};
char status[16] = {0};
// long timestamp;

// while (fscanf(fp, "%s %d %s", filename, &timestamp, status) != EOF) {
intmax_t timestamp_big;   
while (fscanf(fp, "%63s %jd %15s", filename, &timestamp_big, status) == 3) {
  time_t timestamp = (time_t) timestamp_big;
  if (timestamp != timestamp_big) Handle_OutOfRangeError();
  ...

long timestamp склонен к ошибке Y2038 .

...