Skip to content

Commit

Permalink
Update realloc(p,0) semantics
Browse files Browse the repository at this point in the history
This commit changes the behaviour of realloc(p,0) to be free(p) if p!=nullptr, and malloc(0) if p== nullptr.
  • Loading branch information
mjp41 committed Feb 27, 2025
1 parent e954567 commit 44e6844
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 5 deletions.
26 changes: 21 additions & 5 deletions src/snmalloc/global/libc.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,25 @@ namespace snmalloc::libc

SNMALLOC_FAST_PATH_INLINE void* realloc(void* ptr, size_t size)
{
// Glibc treats
// realloc(p, 0) as free(p)
// realloc(nullptr, s) as malloc(s)
// and for the overlap
// realloc(nullptr, 0) as malloc(1)
// Without the first two we don't pass the glibc tests.
// The last one is required by various gnu utilities such as grep, sed.
if (SNMALLOC_UNLIKELY(!is_small_sizeclass(size)))
{
if (SNMALLOC_UNLIKELY(size == 0))
{
if (SNMALLOC_UNLIKELY(ptr == nullptr))
return malloc(1);

dealloc(ptr);
return nullptr;
}
}

size_t sz = alloc_size(ptr);
// Keep the current allocation if the given size is in the same sizeclass.
if (sz == round_size(size))
Expand All @@ -72,13 +91,10 @@ namespace snmalloc::libc
}
dealloc(ptr);
}
else if (SNMALLOC_LIKELY(size == 0))
{
dealloc(ptr);
}
else
{
return set_error();
// Error should be set by alloc on this path already.
SNMALLOC_ASSERT(errno == ENOMEM);
}
return p;
}
Expand Down
5 changes: 5 additions & 0 deletions src/test/func/malloc/malloc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ int main(int argc, char** argv)
test_calloc(0, size, SUCCESS, false);
}

// Check realloc(nullptr,0) behaves like malloc(1)
test_realloc(nullptr, 0, SUCCESS, false);

for (smallsizeclass_t sc = 0; sc < NUM_SMALL_SIZECLASSES; sc++)
{
const size_t size = sizeclass_to_size(sc);
Expand All @@ -277,6 +280,8 @@ int main(int argc, char** argv)
test_realloc(our_malloc(size), size2, SUCCESS, false);
test_realloc(our_malloc(size + 1), size2, SUCCESS, false);
}
// Check realloc(p,0), behaves like free(p), if p != nullptr
test_realloc(our_malloc(size), 0, SUCCESS, true);
}

for (smallsizeclass_t sc = 0; sc < (MAX_SMALL_SIZECLASS_BITS + 4); sc++)
Expand Down

0 comments on commit 44e6844

Please sign in to comment.