[PATCH] [libc++] Remove unaligned type punning from murmurhash/cityhash

Howard Hinnant hhinnant at apple.com
Wed Jul 3 10:41:09 PDT 2013


On Jul 2, 2013, at 5:52 PM, Matthew Dempsky <matthew at dempsky.org> wrote:

> I believe the code below is a conforming C++11 program.  However, I'm
> pretty sure with libc++, this code causes an unaligned word access
> (problem for strict alignment architectures) and also involves type
> punning (problem for -fstrict-aliasing).
> 
> This is because libc++'s hash<basic_string<...>> directly calls the
> murmurhash/cityhash functions on its string data, which in turn
> dereference the memory via size_t pointers.  The allocator below
> ensures the array is oddly aligned; but also because the string data
> is a char array, it's unsafe to dereference it as a size_t or uint32_t
> array.
> 
> Attached patch replaces the type punning with memcpy(), which on
> x86/x86-64 clang optimizes to direct word accesses anyway.
> 
> 
> #include <string>
> #include <iostream>
> #include <cstdlib>
> 
> namespace {
> 
> template <typename T>
> class SillyAlloc
> {
> public:
>    typedef T value_type;
> 
>    SillyAlloc() = default;
>    template <typename U> SillyAlloc(const SillyAlloc<U>&) noexcept {}
> 
>    T* allocate(std::size_t n)
>    {
>        T* p = static_cast<T*>(std::malloc((n + 1) * sizeof(T)));
>        return p ? p + 1 : nullptr;
>    }
> 
>    void deallocate(T* p, std::size_t) noexcept
>    {
>        if (p) std::free(p - 1);
>    }
> };
> 
> typedef std::basic_string<char, std::char_traits<char>, SillyAlloc<char>> SillyString;
> 
> }
> 
> int
> main()
> {
>    SillyString s = "hello";
>    std::hash<SillyString> h;
>    std::cout << h(s) << std::endl;
> }
> <hash-align.diff>

Thanks, Committed revision 185558.

Howard




More information about the cfe-commits mailing list