首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么G++12向量插入优化会破坏代码?

为什么G++12向量插入优化会破坏代码?
EN

Stack Overflow用户
提问于 2022-07-05 09:30:44
回答 1查看 163关注 0票数 1

上一次我用新的GCC12编译了我的项目,它给了我关于内存缓冲区大小错误的警告。此前版本的GCC没有报道过这样的警告。

介绍我的情况的简单代码示例:

代码语言:javascript
复制
#include <vector>                                                              
#include <cstdint>                                                             
#include <iostream>                                                            
                                                                               
struct [[gnu::packed]] S {                                                     
  uint32_t a;                                                                  
  uint8_t  b;                                                                  
  uint16_t c;                                                                  
};                                                                             
                                                                               
std::vector<uint8_t> s_to_bytes(const S &s) {                                  
  S x = s;                                                                     
                                                                               
  std::vector<uint8_t> res;                                                    
  res.insert                                                                   
    ( res.begin()                                                              
    , reinterpret_cast<uint8_t*>(&x)                                           
    , reinterpret_cast<uint8_t*>(&x) + sizeof(S)                               
    );                                                                         
  return res;                                                                  
}                                                                              
                                                                               
int main () {                                                                  
                                                                               
  S s{1,2,3};                                                                  
  auto bytes = s_to_bytes(s);                                                  
  for (auto &x : bytes) std::cout << static_cast<int>(x) << " ";               
  std::cout << std::endl;                                                      
                                                                               
  return 0;                                                                    
}   

当我通过G++12命令编译这段代码时

代码语言:javascript
复制
g++ -Wall -Wextra -O2 -Wpedantic -std=c++20 invalid_optimization.cpp

它打印警告:

代码语言:javascript
复制
inlined from ‘std::vector<unsigned char> s_to_bytes(const S&)’ at invalid_optimization.cpp:16:5:
/usr/include/c++/12/bits/stl_algobase.h:431:30: warning: ‘void* __builtin_memmove(void*, const void*, long unsigned int)’ writing 1 or more bytes into a region of size 0 overflows the destination [-Wstringop-overflow=]
  431 |             __builtin_memmove(__result, __first, sizeof(_Tp) * _Num);
      |             ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In member function ‘_Tp* std::__new_allocator<_Tp>::allocate(size_type, const void*) [with _Tp = unsigned char]’,
    inlined from ‘constexpr _Tp* std::allocator< <template-parameter-1-1> >::allocate(std::size_t) [with _Tp = unsigned char]’ at /usr/include/c++/12/bits/allocator.h:183:40,
    inlined from ‘static constexpr _Tp* std::allocator_traits<std::allocator<_Up> >::allocate(allocator_type&, size_type) [with _Tp = unsigned char]’ at /usr/include/c++/12/bits/alloc_traits.h:464:28,
    inlined from ‘constexpr std::_Vector_base<_Tp, _Alloc>::pointer std::_Vector_base<_Tp, _Alloc>::_M_allocate(std::size_t) [with _Tp = unsigned char; _Alloc = std::allocator<unsigned char>]’ at /usr/include/c++/12/bits/stl_vector.h:378:33,
    inlined from ‘constexpr std::_Vector_base<_Tp, _Alloc>::pointer std::_Vector_base<_Tp, _Alloc>::_M_allocate(std::size_t) [with _Tp = unsigned char; _Alloc = std::allocator<unsigned char>]’ at /usr/include/c++/12/bits/stl_vector.h:375:7,
    inlined from ‘constexpr void std::vector<_Tp, _Alloc>::_M_range_insert(iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = unsigned char*; _Tp = unsigned char; _Alloc = std::allocator<unsigned char>]’ at /usr/include/c++/12/bits/vector.tcc:787:40,
    inlined from ‘constexpr void std::vector<_Tp, _Alloc>::_M_insert_dispatch(iterator, _InputIterator, _InputIterator, std::__false_type) [with _InputIterator = unsigned char*; _Tp = unsigned char; _Alloc = std::allocator<unsigned char>]’ at /usr/include/c++/12/bits/stl_vector.h:1779:19,
    inlined from ‘constexpr std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::insert(const_iterator, _InputIterator, _InputIterator) [with _InputIterator = unsigned char*; <template-parameter-2-2> = void; _Tp = unsigned char; _Alloc = std::allocator<unsigned char>]’ at /usr/include/c++/12/bits/stl_vector.h:1481:22,
    inlined from ‘std::vector<unsigned char> s_to_bytes(const S&)’ at invalid_optimization.cpp:16:5:
/usr/include/c++/12/bits/new_allocator.h:137:55: note: at offset 7 into destination object of size 7 allocated by ‘operator new’
  137 |         return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp)));

此警告显示,进入向量的insert被优化为__builtin_memmove(__result, __first, sizeof(_Tp) * _Num);调用,但大小无效。向量insert文档告诉我们,插入是在范围[first, last)中执行的,所以结构指针的末尾必须指向结构之后的下一个字节,就像迭代器.end()一样,但是GCC从这个有效的代码中进行了无效的memmove调用,它可能得到了结构大小+1,而不仅仅是结构大小。看起来__builtin_memmove只是firstlast指针的不同,而不是last - first - 1

我的问题是:我的vector::insert使用是无效的还是GCC12优化错误?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-05 09:51:07

我的问题是:我的vector::insert使用是无效的还是GCC12优化错误?

正如评论中提到的,这是gcc的一个警告错误。减缩

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

std::vector<int> s_to_bytes() {
  std::vector<int> res;
  std::array<int, 4> s{};
  res.insert(res.begin(), s.begin(), s.end());
  return res;
}

上面的代码无疑是格式良好的,但是gcc-12给出了一个意外的__builtin_memmove溢出警告。

Bug提交了106199

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

https://stackoverflow.com/questions/72867072

复制
相关文章

相似问题

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