GCC 7, aligned_storage and "dereferenced pointer type will violate strict anti-aliasing rules"

The code I wrote was error free in GCC 4.9, GCC 5, and GCC 6. It was also without warning with some old experimental snapshots of GCC 7 (e.g. 7-20170409). But in the last shot (including the first RC), he began to raise a warning about an alias. The code basically boils down to the following:

#include <type_traits>

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

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

Compilation with the latest 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;

(Interestingly, the warning does not occur when optimization is disabled)

Compiling with GCC 6 gives no warning.

Now I'm wondering, the code above is definitely HAS type-punning, not a question about it, but not std::aligned_storageintended to be used that way?

, , , 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*/);
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

, : ?

+4
2

, undefined - . , .

, , - (, , ).

#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';
}

, .

+2

undefined ( ). ++ - . ; .

aligned_storage - . , place-new. , . , , ; , , , .

main :

new(&storage) int(42);

, , - , .

[basic.life] , , , , , - , , .

. .


cppreference aligned_storage . , , " ", , - :

new(data+m_size) T(std::forward<Args>(args)...);

return *reinterpret_cast<const T*>(data+pos);, pos , , .

+1

Source: https://habr.com/ru/post/1676035/


All Articles