ctime_r 在 docker 中失败
ctime_r failed in docker
我在 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, ×tamp, status) != EOF) {
char *ts = ctime_r(×tamp, tbuf);
if (ts) {
ts[strlen(ts)-1] = '[=12=]';
sprintf(buf, "%-32s%-32s%-8s", filename, ts, status);
} else {
sprintf(buf, "%-32s%-32s%-8s", filename, "Miss", status);
}
}
pclose(fp);
}
但是tbuf的内容是"Sat Oct 29 21:37:05 44614",ts是NULL
我认为时间戳是一个有效值。但为什么失败了?
why it failed?
OP 后来添加了代码并报告了 。
启用警告后,我的编译器也会发出警告。
warning: format '%d' expects argument of type 'int *', but argument 4 has type 'long int *'
从文本文件中读取 time_t
很棘手。范围、纪元、数据类型属性都在起作用。此外,作为文件中的文本化数据,属性可能与编写它的系统不同。请注意 time_t
.
没有 fscanf()
说明符
现在,让我们假设文本时间戳只是数字并且对应于一个整数 time_t
,即使我们不知道整数类型的细节。更高级的技术不需要这些假设。
使用可用的最宽符号类型读取时间戳,例如 intmax_t
(或在 C99 之前的系统上为 long
)。一些范围检查是值得的。我还建议使用相同的宽字体来编写 time_t
。
注意:最好将 fscanf()
return 值与一个预期值 (3) 进行比较,而不是仅与各种意外值(EOF、0、1、2)中的一个进行比较。对字符串输入使用宽度限制。
char filename[64] = {0};
char status[16] = {0};
// long timestamp;
// while (fscanf(fp, "%s %d %s", filename, ×tamp, status) != EOF) {
intmax_t timestamp_big;
while (fscanf(fp, "%63s %jd %15s", filename, ×tamp_big, status) == 3) {
time_t timestamp = (time_t) timestamp_big;
if (timestamp != timestamp_big) Handle_OutOfRangeError();
...
long timestamp
容易出现 Y2038 bug.
我在 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, ×tamp, status) != EOF) {
char *ts = ctime_r(×tamp, tbuf);
if (ts) {
ts[strlen(ts)-1] = '[=12=]';
sprintf(buf, "%-32s%-32s%-8s", filename, ts, status);
} else {
sprintf(buf, "%-32s%-32s%-8s", filename, "Miss", status);
}
}
pclose(fp);
}
但是tbuf的内容是"Sat Oct 29 21:37:05 44614",ts是NULL
我认为时间戳是一个有效值。但为什么失败了?
why it failed?
OP 后来添加了代码并报告了
启用警告后,我的编译器也会发出警告。
warning: format '%d' expects argument of type 'int *', but argument 4 has type 'long int *'
从文本文件中读取 time_t
很棘手。范围、纪元、数据类型属性都在起作用。此外,作为文件中的文本化数据,属性可能与编写它的系统不同。请注意 time_t
.
fscanf()
说明符
现在,让我们假设文本时间戳只是数字并且对应于一个整数 time_t
,即使我们不知道整数类型的细节。更高级的技术不需要这些假设。
使用可用的最宽符号类型读取时间戳,例如 intmax_t
(或在 C99 之前的系统上为 long
)。一些范围检查是值得的。我还建议使用相同的宽字体来编写 time_t
。
注意:最好将 fscanf()
return 值与一个预期值 (3) 进行比较,而不是仅与各种意外值(EOF、0、1、2)中的一个进行比较。对字符串输入使用宽度限制。
char filename[64] = {0};
char status[16] = {0};
// long timestamp;
// while (fscanf(fp, "%s %d %s", filename, ×tamp, status) != EOF) {
intmax_t timestamp_big;
while (fscanf(fp, "%63s %jd %15s", filename, ×tamp_big, status) == 3) {
time_t timestamp = (time_t) timestamp_big;
if (timestamp != timestamp_big) Handle_OutOfRangeError();
...
long timestamp
容易出现 Y2038 bug.