[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