gpt4 book ai didi

c++ - GCC 7,aligned_storage 和 "dereferencing type-punned pointer will break strict-aliasing rules"

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:33:09 28 4
gpt4 key购买 nike

我编写的代码在 GCC 4.9、GCC 5 和 GCC 6 中没有警告。它在一些较旧的 GCC 7 实验快照(例如 7-20170409)中也没有警告。但在最近的快照(包括第一个 RC)中,它开始产生关于别名的警告。代码基本上可以归结为:

#include <type_traits>

std::aligned_storage<sizeof(int), alignof(int)>::type storage;

int main()
{
*reinterpret_cast<int*>(&storage) = 42;
}

使用最新的 GCC 7 RC 编译:

$ g++ -Wall -O2 -c main.cpp
main.cpp: In function 'int main()':
main.cpp:7:34: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
*reinterpret_cast<int*>(&storage) = 42;

(有趣的观察是禁用优化时不会产生警告)

使用 GCC 6 编译完全没有警告。

现在我想知道,上面的代码肯定有类型双关,这是毫无疑问的,但是 std::aligned_storage 不应该那样使用吗?

例如给出的示例代码here GCC 7 通常不会产生警告,但仅仅是因为:

  • std::string 不受影响,
  • std::aligned_storage 使用偏移量访问。

通过将 std::string 更改为 int,删除对 std::aligned_storage 的偏移访问并删除不相关的部分,您将得到:

#include <iostream>
#include <type_traits>
#include <string>

template<class T, std::size_t N>
class static_vector
{
// properly aligned uninitialized storage for N T's
typename std::aligned_storage<sizeof(T), alignof(T)>::type data[N];
std::size_t m_size = 0;

public:

// Access an object in aligned storage
const T& operator[](std::size_t pos) const
{
return *reinterpret_cast<const T*>(data/*+pos*/); // <- note here, offset access disabled
}
};

int main()
{
static_vector<int, 10> v1;
std::cout << v1[0] << '\n' << v1[1] << '\n';
}

这会产生完全相同的警告:

main.cpp: In instantiation of 'const T& static_vector<T, N>::operator[](std::size_t) const [with T = int; unsigned int N = 10; std::size_t = unsigned int]':
main.cpp:24:22: required from here
main.cpp:17:16: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
return *reinterpret_cast<const T*>(data/*+pos*/);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

所以我的问题是 - 这是错误还是功能?

最佳答案

我无法回答是否真的存在由于别名导致的未定义行为的可能性,或者警告是否没有根据。我发现别名主题是一个相当复杂的雷区。

但是,我认为您的代码的以下变体消除了别名问题而没有任何开销(并且可能更具可读性)。

#include <iostream>
#include <type_traits>
#include <string>

template<class T, std::size_t N>
class static_vector
{
// properly aligned uninitialized storage for N T's
union storage_t_ {
T item;
typename std::aligned_storage<sizeof(T), alignof(T)>::type aligned_member;
};
storage_t_ data[N];

std::size_t m_size = 0;

public:

// Access an object in aligned storage
const T& operator[](std::size_t pos) const
{
return data[0].item;
}
};

int main()
{
static_vector<int, 10> v1;
std::cout << v1[0] << '\n' << v1[1] << '\n';
}

对于你的情况是否可以接受,我不能确定。

关于c++ - GCC 7,aligned_storage 和 "dereferencing type-punned pointer will break strict-aliasing rules",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43711567/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com