Fix a serious bug in handmade_aligned_realloc: original data have to be moved if the alignment offset differs.

This commit is contained in:
Gael Guennebaud 2013-04-10 13:58:20 +02:00
parent f7e52d22d4
commit 7e04d7db02

View File

@ -94,11 +94,11 @@ inline void throw_std_bad_alloc()
/** \internal Like malloc, but the returned pointer is guaranteed to be 16-byte aligned. /** \internal Like malloc, but the returned pointer is guaranteed to be 16-byte aligned.
* Fast, but wastes 16 additional bytes of memory. Does not throw any exception. * Fast, but wastes 16 additional bytes of memory. Does not throw any exception.
*/ */
inline void* handmade_aligned_malloc(size_t size) inline void* handmade_aligned_malloc(std::size_t size)
{ {
void *original = std::malloc(size+16); void *original = std::malloc(size+16);
if (original == 0) return 0; if (original == 0) return 0;
void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16); void *aligned = reinterpret_cast<void*>((reinterpret_cast<std::size_t>(original) & ~(std::size_t(15))) + 16);
*(reinterpret_cast<void**>(aligned) - 1) = original; *(reinterpret_cast<void**>(aligned) - 1) = original;
return aligned; return aligned;
} }
@ -114,13 +114,18 @@ inline void handmade_aligned_free(void *ptr)
* Since we know that our handmade version is based on std::realloc * Since we know that our handmade version is based on std::realloc
* we can use std::realloc to implement efficient reallocation. * we can use std::realloc to implement efficient reallocation.
*/ */
inline void* handmade_aligned_realloc(void* ptr, size_t size, size_t = 0) inline void* handmade_aligned_realloc(void* ptr, std::size_t size, std::size_t = 0)
{ {
if (ptr == 0) return handmade_aligned_malloc(size); if (ptr == 0) return handmade_aligned_malloc(size);
void *original = *(reinterpret_cast<void**>(ptr) - 1); void *original = *(reinterpret_cast<void**>(ptr) - 1);
std::ptrdiff_t previous_offset = static_cast<char *>(ptr)-static_cast<char *>(original);
original = std::realloc(original,size+16); original = std::realloc(original,size+16);
if (original == 0) return 0; if (original == 0) return 0;
void *aligned = reinterpret_cast<void*>((reinterpret_cast<size_t>(original) & ~(size_t(15))) + 16); void *aligned = reinterpret_cast<void*>((reinterpret_cast<std::size_t>(original) & ~(std::size_t(15))) + 16);
void *previous_aligned = static_cast<char *>(original)+previous_offset;
if(aligned!=previous_aligned)
std::memmove(aligned, previous_aligned, size);
*(reinterpret_cast<void**>(aligned) - 1) = original; *(reinterpret_cast<void**>(aligned) - 1) = original;
return aligned; return aligned;
} }
@ -129,7 +134,7 @@ inline void* handmade_aligned_realloc(void* ptr, size_t size, size_t = 0)
*** Implementation of generic aligned realloc (when no realloc can be used)*** *** Implementation of generic aligned realloc (when no realloc can be used)***
*****************************************************************************/ *****************************************************************************/
void* aligned_malloc(size_t size); void* aligned_malloc(std::size_t size);
void aligned_free(void *ptr); void aligned_free(void *ptr);
/** \internal /** \internal