为什么“-flto”沉默 GCC 的警告 "stringop-truncation"
Why "-flto" silent GCC's warning "stringop-truncation"
我知道较新的 GCC 版本对可能错误的字符串操作“stringop-truncation”引入了警告
下面是我可以轻松触发此警告的示例代码:
$ cat strncpy-warning.cxx
#include <cstring>
extern char g_buf[16];
void mycopy ( const char* src_c_str )
{
strncpy ( g_buf, src_c_str, sizeof ( g_buf ) );
}
使用以下标志编译它会触发此警告:
$ g++ --version
g++ (GCC) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ -Wall -std=c++14 -Wextra -Werror -O3 -c strncpy-warning.cxx
strncpy-warning.cxx: In function ‘void mycopy(const char*)’:
strncpy-warning.cxx:7:13: error: ‘char* strncpy(char*, const char*, size_t)’ specified bound 16 equals destination size [-Werror=stringop-truncation]
strncpy ( g_buf, src_c_str, sizeof ( g_buf ) );
~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
这是预期的,但是,如果我向标志添加 -flto
,则此警告消失并生成目标文件:
$ g++ -Wall -std=c++14 -Wextra -Werror -O3 -c strncpy-warning.cxx -flto
$ ls strncpy-warning.o
strncpy-warning.o
显然,-flto
会捕获一些编译时警告,所以不确定为什么 stringop-truncation
没有被捕获,例如:
$ cat strncpy-warning.cxx
#include <cstring>
extern char g_buf[16];
void mycopy ( const char* src_c_str, const char* unused )
{
strncpy ( g_buf, src_c_str, sizeof ( g_buf ) );
}
$ g++ -Wall -std=c++14 -Wextra -Werror -O3 -c strncpy-warning.cxx -flto
strncpy-warning.cxx: In function ‘void mycopy(const char*, const char*)’:
strncpy-warning.cxx:5:50: error: unused parameter ‘unused’ [-Werror=unused-parameter]
void mycopy ( const char* src_c_str, const char* unused )
~~~~~~~~~~~~^~~~~~
cc1plus: all warnings being treated as errors
所以问题是:
- 这是预期的行为吗?
- 我知道为源文件指定
-flto
后,GCC 会将特殊内容写入生成的目标文件 ( *.o
),但问题是为什么 GCC 会跳过警告?是故意的吗?
- 有没有办法在给出
-flto
的情况下启用此警告?
- 或者上面的第 3 点是否有意义?
非常感谢!
大致来说,GCC有两种警告:
- 简单分析源码产生的警告
- 复杂数据流分析生成的警告
第一种是未使用的参数:在函数中根本不使用参数是微不足道的。
strncpy
的错误用法是,除了琐碎的情况,第二种:编译器需要了解 strncpy
的第一个和第三个参数之间的关系,它需要知道实际(或至少是象征性的)值在第三个参数中传递,它需要知道第一个参数中可用的实际(或至少是象征性的)大小。
第一种警告由前端解析器生成。因此,它总是会触发。
第二种是同一个优化代码的组件生成的,因为只有这个组件才有必要的信息。在 -flto
模式下,此组件不会 运行 用于单个源文件。
第二种有时也取决于正在执行的特定优化:如果您将第一个命令行中的优化级别更改为 -O1
,则也不会发出警告。
我知道较新的 GCC 版本对可能错误的字符串操作“stringop-truncation”引入了警告
下面是我可以轻松触发此警告的示例代码:
$ cat strncpy-warning.cxx
#include <cstring>
extern char g_buf[16];
void mycopy ( const char* src_c_str )
{
strncpy ( g_buf, src_c_str, sizeof ( g_buf ) );
}
使用以下标志编译它会触发此警告:
$ g++ --version
g++ (GCC) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ -Wall -std=c++14 -Wextra -Werror -O3 -c strncpy-warning.cxx
strncpy-warning.cxx: In function ‘void mycopy(const char*)’:
strncpy-warning.cxx:7:13: error: ‘char* strncpy(char*, const char*, size_t)’ specified bound 16 equals destination size [-Werror=stringop-truncation]
strncpy ( g_buf, src_c_str, sizeof ( g_buf ) );
~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
这是预期的,但是,如果我向标志添加 -flto
,则此警告消失并生成目标文件:
$ g++ -Wall -std=c++14 -Wextra -Werror -O3 -c strncpy-warning.cxx -flto
$ ls strncpy-warning.o
strncpy-warning.o
显然,-flto
会捕获一些编译时警告,所以不确定为什么 stringop-truncation
没有被捕获,例如:
$ cat strncpy-warning.cxx
#include <cstring>
extern char g_buf[16];
void mycopy ( const char* src_c_str, const char* unused )
{
strncpy ( g_buf, src_c_str, sizeof ( g_buf ) );
}
$ g++ -Wall -std=c++14 -Wextra -Werror -O3 -c strncpy-warning.cxx -flto
strncpy-warning.cxx: In function ‘void mycopy(const char*, const char*)’:
strncpy-warning.cxx:5:50: error: unused parameter ‘unused’ [-Werror=unused-parameter]
void mycopy ( const char* src_c_str, const char* unused )
~~~~~~~~~~~~^~~~~~
cc1plus: all warnings being treated as errors
所以问题是:
- 这是预期的行为吗?
- 我知道为源文件指定
-flto
后,GCC 会将特殊内容写入生成的目标文件 (*.o
),但问题是为什么 GCC 会跳过警告?是故意的吗? - 有没有办法在给出
-flto
的情况下启用此警告? - 或者上面的第 3 点是否有意义?
非常感谢!
大致来说,GCC有两种警告:
- 简单分析源码产生的警告
- 复杂数据流分析生成的警告
第一种是未使用的参数:在函数中根本不使用参数是微不足道的。
strncpy
的错误用法是,除了琐碎的情况,第二种:编译器需要了解 strncpy
的第一个和第三个参数之间的关系,它需要知道实际(或至少是象征性的)值在第三个参数中传递,它需要知道第一个参数中可用的实际(或至少是象征性的)大小。
第一种警告由前端解析器生成。因此,它总是会触发。
第二种是同一个优化代码的组件生成的,因为只有这个组件才有必要的信息。在 -flto
模式下,此组件不会 运行 用于单个源文件。
第二种有时也取决于正在执行的特定优化:如果您将第一个命令行中的优化级别更改为 -O1
,则也不会发出警告。