【发布时间】:2019-02-03 14:48:58
【问题描述】:
这是程序:
#include <stdio.h>
#include <libgen.h>
#include <stdlib.h>
#include <time.h>
#define DATE_SIZE 10
// Declare global variables.
char *program_name = NULL;
int main (int argc, char *argv[])
{
// Declare variables.
time_t t = time(NULL);
struct tm tm = *localtime(&t);
char date[DATE_SIZE + 1] = {0};
// Store today's date in a string for comparison.
if(sprintf(date, "%d/%d/%d", tm.tm_mon + 1, tm.tm_mday, tm.tm_year - 100) < 0)
{
fprintf(stderr, "%s: main error: sprintf failed.\n", program_name);
exit(EXIT_FAILURE);
}
// Print date to user.
printf("Date: %s\n", date);
// Exit gracefully.
exit(EXIT_SUCCESS);
}
编译如下:
gcc -Wall -Werror -O3 -o program program.c
我还有两台机器都在运行 Arch linux:
Linux 笔记本电脑 4.15.7-1-ARCH #1 SMP PREEMPT 2018 年 2 月 28 日星期三 19:01:57 UTC x86_64 GNU/Linux
Linux 存储 4.14.66-1-ARCH #1 SMP 2018 年 8 月 25 日星期六 01:09:50 UTC armv6l GNU/Linux
当我在笔记本电脑上编译时,它很干净并且运行完美。在存储服务器上编译时,出现以下错误:
program.c: In function 'main':
program.c:20:5: error: '/' directive writing 1 byte into a region of size between 0 and 10 [-Werror=format-overflow=]
if(sprintf(date, "%d/%d/%d", tm.tm_mon + 1, tm.tm_mday, tm.tm_year - 100) < 0)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
program.c:20:5: note: directive argument in the range [-2147483648, 2147483547]
program.c:20:5: note: 'sprintf' output between 6 and 36 bytes into a destination of size 11
cc1: all warnings being treated as errors
为什么会有差异?
更新
所有 cmets 似乎都在处理如何修复错误。首先,您需要知道这是一个最小化的程序。我创建的日期与我没有创建的日期进行比较。因此采用 mm/dd/yy 格式。此外,大多数在名称中包含“n”的函数(strncpy、snprintf...)都适用于您不知道数据或者它是用户生成的数据。我将其视为惰性编程,因为您不知道您正在使用的数据。另外,我知道这个程序在 82 年内不会使用。
不,我的问题要处理编译结果的差异。
【问题讨论】:
-
只是警告您
"%d/%d/%d"可能包含超过 11 个字节,因此可能会溢出。 -
正如奥西里斯所说;还建议使用
snprintf():-) -
嗯,再想一想,即使是 16 位
int类型的系统溢出缓冲区也没有问题。好奇为什么它只在一个系统上发出警告。不同版本的 GCC? -
%d/%d/%d(月/日/年)很少能很好地表示日期。尝试根据 ISO 8601 使用 YYYY-MM-DD。另请参阅 xkcd.com/1179
-
如果您的问题是关于编译结果的差异,请附上编译器版本 (
gcc -v)。