GCC 优化:fgets 引起的错误
GCC Optimization: Error caused by fgets
我在我的 Mac 上编译代码并启用 GCC 优化标志 -O3
以加快执行时间。这在我的本地机器上完美运行,并导致速度提高 2/3。
但是,我尝试在 Amazon EC2 上编译代码,因为我正在处理一个大型数据集。使用 -O3
优化标志会导致以下警告
warning: call to ‘__fgets_chk_warn’ declared with attribute warning:
fgets called with bigger size than length of destination buffer
在各自的函数中,逐行解析一个文本文件。但是,我真的不明白为什么我最终会收到警告。函数代码如下:
int loadPriceData(const char *filename, double *target) {
char line[40];
FILE *fp;
fp = fopen(filename, "r");
if (fp == NULL) {
return -1;
}
int i = 0;
while (fgets(line, 80, fp) != NULL) {
sscanf(line, "%lf\n", target + i);
i += 1;
}
fclose(fp);
return i; // Return number of elements
}
默认情况下,target
是指向具有 10000
个元素的数组的指针。条目数事先不知道,但由函数返回。
您确实在调用 fgets(line, 80, fp)
,但目标数组 line
被定义为 40
字符数组。 Amazon EC2 上的编译器比您的配置更好或更智能。如果文件包含超过 39 字节的行,这就是一个真正的错误。
顺便说一下,在 Mac 上作为 gcc
调用的编译器通常是 clang
的一个实例。试试 gcc --version
.
请注意,您的程序不会检查是否读取了太多数据,也不会检查 sscanf()
转换是否成功。两者都会导致未定义的行为。
这是一个更安全的版本:
int loadPriceData(const char *filename, double *target, int nb_items) {
char line[80];
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
return -1;
}
int i = 0;
while (fgets(line, sizeof line, fp) != NULL) {
if (i < nb_items) {
if (sscanf(line, "%lf", target + i) != 1)
target[i] = 0;
}
i += 1;
}
fclose(fp);
return i; // Return number of elements
}
我在我的 Mac 上编译代码并启用 GCC 优化标志 -O3
以加快执行时间。这在我的本地机器上完美运行,并导致速度提高 2/3。
但是,我尝试在 Amazon EC2 上编译代码,因为我正在处理一个大型数据集。使用 -O3
优化标志会导致以下警告
warning: call to ‘__fgets_chk_warn’ declared with attribute warning: fgets called with bigger size than length of destination buffer
在各自的函数中,逐行解析一个文本文件。但是,我真的不明白为什么我最终会收到警告。函数代码如下:
int loadPriceData(const char *filename, double *target) {
char line[40];
FILE *fp;
fp = fopen(filename, "r");
if (fp == NULL) {
return -1;
}
int i = 0;
while (fgets(line, 80, fp) != NULL) {
sscanf(line, "%lf\n", target + i);
i += 1;
}
fclose(fp);
return i; // Return number of elements
}
默认情况下,target
是指向具有 10000
个元素的数组的指针。条目数事先不知道,但由函数返回。
您确实在调用 fgets(line, 80, fp)
,但目标数组 line
被定义为 40
字符数组。 Amazon EC2 上的编译器比您的配置更好或更智能。如果文件包含超过 39 字节的行,这就是一个真正的错误。
顺便说一下,在 Mac 上作为 gcc
调用的编译器通常是 clang
的一个实例。试试 gcc --version
.
请注意,您的程序不会检查是否读取了太多数据,也不会检查 sscanf()
转换是否成功。两者都会导致未定义的行为。
这是一个更安全的版本:
int loadPriceData(const char *filename, double *target, int nb_items) {
char line[80];
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
return -1;
}
int i = 0;
while (fgets(line, sizeof line, fp) != NULL) {
if (i < nb_items) {
if (sscanf(line, "%lf", target + i) != 1)
target[i] = 0;
}
i += 1;
}
fclose(fp);
return i; // Return number of elements
}