-
Notifications
You must be signed in to change notification settings - Fork 49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix memalign error in debug-malloc #1448
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,9 +5,11 @@ | |
#include <stddef.h> | ||
#include <stdint.h> | ||
#include <stdio.h> | ||
#include <assert.h> | ||
#include <string.h> | ||
|
||
#include <myst/backtrace.h> | ||
#include <myst/printf.h> | ||
#include <myst/debugmalloc.h> | ||
#include <myst/defs.h> | ||
#include <myst/malloc.h> | ||
|
@@ -20,6 +22,8 @@ | |
#define ENABLE_MALLOC_MEMSET | ||
#define ENABLE_FREE_MEMSET | ||
|
||
// #define DEBUG_MEMALIGN | ||
|
||
/* | ||
**============================================================================== | ||
** | ||
|
@@ -173,6 +177,12 @@ MYST_INLINE void* _get_block_address(void* ptr) | |
return (uint8_t*)ptr - sizeof(header_t) - padding_size; | ||
} | ||
|
||
MYST_INLINE void* _get_block_address_v2(void* ptr) | ||
{ | ||
header_t* header = _get_header(ptr); | ||
return (uint8_t*)header - header->padding; | ||
} | ||
|
||
MYST_INLINE size_t _calculate_block_size(size_t alignment, size_t size) | ||
{ | ||
size_t r = 0; | ||
|
@@ -330,6 +340,17 @@ void myst_debug_free(void* ptr) | |
|
||
void* block = _get_block_address(ptr); | ||
|
||
/* sanity cross check for block address */ | ||
if (block != _get_block_address_v2(ptr)) | ||
{ | ||
assert("_get_block_address_v2() failed"); | ||
} | ||
|
||
#ifdef DEBUG_MEMALIGN | ||
printf("free: block=%p header=%p delta=%zu\n", | ||
block, header, (const uint8_t*)header - (const uint8_t*)block); | ||
#endif | ||
|
||
/* fill block with 0xdd (deallocated) bytes */ | ||
#ifdef ENABLE_FREE_MEMSET | ||
memset(block, 0xDD, _get_block_size(ptr)); | ||
|
@@ -393,10 +414,39 @@ int myst_debug_posix_memalign(void** memptr, size_t alignment, size_t size) | |
const size_t block_size = _calculate_block_size(alignment, size); | ||
void* block = NULL; | ||
header_t* header = NULL; | ||
size_t rsize = _round_up_to_multiple(size, sizeof(uint64_t)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need to align the data size to 8 bytes? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The data is padded at the end up to an 8-byte boundary. This forces the footer to be aligned on an 8-byte boundary. |
||
|
||
if (memptr) | ||
*memptr = NULL; | ||
|
||
if (!memptr) | ||
return EINVAL; | ||
|
||
/* | ||
** [padding][header][block][footer] | ||
** ^ ^ | ||
** | | | ||
** X Y | ||
** | ||
** Note: both X and Y are on the alignment boundary | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Who do we need to align the header, but not the footer? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch! We align the footer on an 8-byte-boundary but my picture did not reflect that. I updated the picture and added some more explanation. |
||
*/ | ||
|
||
#ifdef DEBUG_MEMALIGN | ||
printf("memalign: padding=%zu header=%zu block=%zu footer=%zu\n", | ||
padding_size, sizeof(header_t), size, sizeof(footer_t)); | ||
#endif | ||
|
||
/* the sum of the parts should add up to total block size */ | ||
if (padding_size + sizeof(header_t) + rsize + sizeof(footer_t) | ||
!= block_size) | ||
{ | ||
return EINVAL; | ||
} | ||
|
||
/* the data should be aligned on the given boundary */ | ||
if ((padding_size + sizeof(header_t)) % alignment) | ||
return EINVAL; | ||
|
||
if (!_is_ptrsize_multiple(alignment) || !_is_pow2(alignment)) | ||
return EINVAL; | ||
|
||
|
@@ -421,6 +471,7 @@ void* myst_debug_memalign(size_t alignment, size_t size) | |
alignment = _round_up_to_multiple(alignment, sizeof(void*)); | ||
|
||
myst_debug_posix_memalign(&ptr, alignment, size); | ||
|
||
return ptr; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still need
_get_block_address
v1?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could eliminate v1, but I left it as a cross check in case the two functions fail to produce the same quantity. The v2 version is just intended as a sanity check (so if v1 != v2 then we return EINVAL).