我有这段代码(让我们称之为
problem.cpp
):#include <string>
using str = std::wstring;
static str foo(str text = str())
{
text.resize(4);
return text;
}
int main()
{
str a = foo();
return 0;
}
使用带有-O1
和C++20兼容性的GCC(版本12.2.1)调用(g++ problem.cpp -Werror -O1 -std=c++20
)会导致以下错误:
In file included from /usr/include/features.h:490,
from /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/x86_64-pc-linux-gnu/bits/os_defines.h:39,
from /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/x86_64-pc-linux-gnu/bits/c++config.h:655,
from /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/string:38,
from problem.cpp:1:
In function ‘wchar_t* wmemcpy(wchar_t*, const wchar_t*, size_t)’,
inlined from ‘static constexpr std::char_traits<wchar_t>::char_type* std::char_traits<wchar_t>::copy(char_type*, const char_type*, std::size_t)’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/bits/char_traits.h:558:16,
inlined from ‘constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = wchar_t; _Traits = std::char_traits<wchar_t>; _Alloc = std::allocator<wchar_t>]’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/bits/basic_string.h:675:23,
inlined from ‘str foo(str)’ at problem.cpp:7:9,
inlined from ‘int main()’ at problem.cpp:12:14:
/usr/include/bits/wchar2.h:39:10: error: call to ‘__wmemcpy_chk_warn’ declared with attribute warning: wmemcpy called with length bigger than size of destination buffer [-Werror=attribute-warning]
39 | return __glibc_fortify_n (wmemcpy, __n, sizeof (wchar_t),
| ^~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
有趣的是,我无法通过使用 std::string
(与 std::wstring
相比)、使用较小的 resize 值或任何低于 C++20 或 O1
的东西来触发此错误。
对我而言,这段代码片段看起来并不可疑。不幸的是,我无法在 Godbolt 上复现此问题。也许 Godbolt 使用了另一个和/或未加强的 glibc 版本?我正在 Gentoo Linux 上使用 glibc 2.36,但我也在 Ubuntu 上看到过这种情况。然而,在怀疑 glibc 或编译器存在漏洞之前,我想在这里打听一下是否真的是误报。
有什么想法吗?
编辑:与此同时,我已经可以使用 Godbolt 复现类似的错误: https://godbolt.org/z/joPaYKK11
g++ -O -D_FORTIFY_SOURCE=2 -std=c++20
命令。 - KamilCukwmemcpy
,则会无效,编译器知道这一点,因为它看到了长度的设置。然而,在现实中,不可见的g
保证if
条件不满足。但是,每当对象大小和长度参数在编译时已知但不匹配时,glibc使用__attribute__(warning)
。该属性会在代码未被优化消除时产生警告。 - user17732522f()
基本上是在str
构造函数内联后得到的结果,除了有一个嵌套的函数调用没有被内联(在简化的示例中为g
),因此其效果对编译器来说是未知的。 - user17732522