首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >gcc -std=c++20编译器标志-Wrestrict未理解。这一警告有道理吗?

gcc -std=c++20编译器标志-Wrestrict未理解。这一警告有道理吗?
EN

Stack Overflow用户
提问于 2022-12-04 15:18:25
回答 1查看 43关注 0票数 0

下面的代码用gcc 11.3.0编译得很好。

代码语言:javascript
复制
#include <string>

std::string homeName( const std::string& home, std::string surl )
{
   if ( surl.find( home ) == 0 )
   {
      surl.replace( 0, home.size(), "~" ); // shorten url by replacing $HOME with "~"
   }

   return surl;
}

也就是说,如果字符串surl以home的值开头,则将头替换为倾斜,"~“。然而,当我切换到gcc 12.2.1,有一个警告(-Wrestrict,包括在-Wall中),我不明白。警告是针对具有replace命令的行的。完整的消息(像往常一样几乎不可读)给出了下面的内容,但首先是一些试验的结果:我将完整的编译器命令裁剪到基本部分。

代码语言:javascript
复制
gcc11  -Wrestrict -O2 -std=c++20 -c file.cpp        # Ok, with/without optimisations. 
gcc12  -Wrestrict -O2 -std=c++20 -c file.cpp        # warning, but not with std=c++17
gcc12  -Wrestrict =O1 -std=c++20 -c file.cpp        # Ok

从手册中:

-Wrestrict:当被限制限定参数引用的对象(或者,在C++中,一个__限制-限定参数)被另一个参数别名时,或者当这些对象之间的副本重叠时,警告。但是,我并不真正理解这如何适用于上面的代码。有人能解释一下发生了什么事吗?

下面是一些示例输出:

代码语言:javascript
复制
[655] build> g++ --version
g++ (SUSE Linux) 12.2.1 20220830 [revision e927d1cf141f221c5a32574bde0913307e140984]
Copyright (C) 2022 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.

[655] build> g++ -Wrestrict -O2 -std=c++20 -c file.cpp
In file included from /usr/include/c++/12/string:40,
                 from file.cpp:1:
In static member function ‘static constexpr std::char_traits<char>::char_type* std::char_traits<char>::copy(char_type*, const char_type*, std::size_t)’,
    inlined from ‘static constexpr void std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_S_copy(_CharT*, const _CharT*, size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /usr/include/c++/12/bits/basic_string.h:423:21,
    inlined from ‘static constexpr void std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_S_copy(_CharT*, const _CharT*, size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /usr/include/c++/12/bits/basic_string.h:418:7,
    inlined from ‘constexpr std::__cxx11::basic_string<_CharT, _Traits, _Allocator>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::_M_replace(size_type, size_type, const _CharT*, size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /usr/include/c++/12/bits/basic_string.tcc:532:22,
    inlined from ‘constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::replace(size_type, size_type, const _CharT*, size_type) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /usr/include/c++/12/bits/basic_string.h:2171:19,
    inlined from ‘constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::replace(size_type, size_type, const _CharT*) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ at /usr/include/c++/12/bits/basic_string.h:2196:22,
    inlined from ‘std::string homeName(const std::string&, std::string)’ at file.cpp:7:19:
/usr/include/c++/12/bits/char_traits.h:431:56: warning: ‘void* __builtin_memcpy(void*, const void*, long unsigned int)’ accessing 9223372036854775810 or more bytes at offsets [2, 9223372036854775807] and 1 may overlap up to 9223372036854775813 bytes at offset -3 [-Wrestrict]
  431 |         return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
      |                                        ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
[656] build> 
EN

回答 1

Stack Overflow用户

发布于 2022-12-04 15:34:05

正在发生的是一个明显的gcc错误。显示的代码没有什么问题(除了下面提到的不相关的bug)。在切换到gcc 12之后,同样的诊断从我自己的代码中开始出现。

我怀疑这个具体的例子是bug 100366的另一个例子,它最初出现在gcc 11中,但由于受到额外的内部编译器优化的影响,这种情况在gcc 12中似乎变得更加普遍。

这个警告似乎是无害的。但这很烦人。到目前为止,使用我自己的代码,我已经成功地提出了一些使其消失的调整。在这种情况下,如果我将其重写为:

代码语言:javascript
复制
   if ( surl.find( home ) == 0 )
   {
       surl="~" + surl.substr(home.size());
   }

也就是说,如果字符串surl以home的值开头,用一个倾斜的值替换头部,

如果是这样的话,那么显示的代码就会略为漏掉标记。因为如果我的home目录是/home/sam,这将用~v/foo代替/home/samv/foo,这显然是错误的(您的原始版本也有相同的错误)。

因此,除了修复编译器警告之外,您还应该仔细考虑正确的逻辑应该是什么。乍一看,它并不像看上去那么简单。文件名不仅仅是随机字符串。他们有结构,也有一点组织。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74677951

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档