[libc-commits] [PATCH] D157653: [libc][WIP] move realloc into alloc_checker
Roland McGrath via Phabricator via libc-commits
libc-commits at lists.llvm.org
Fri Aug 11 11:25:50 PDT 2023
mcgrathr added a comment.
What I meant about a custom `operator new` to do `realloc` was something like this (C++20 example and without the AllocChecker arg, which would be added here too):
#include <span>
#include <cstdlib>
template<typename T>
[[nodiscard]] inline void* operator new[] (size_t size, std::span<T> old) noexcept {
void* ptr = ::realloc(old.data(), old.size_bytes() + size);
if (!ptr) { return nullptr; }
return static_cast<char*>(ptr) + old.size_bytes();
}
struct S { int x = 23; };
S* extend(S* old, size_t count) {
return new (std::span{old,count}) S[count];
}
int* extend(int* old, size_t count) {
return new (std::span{old,count}) int[count];
}
Instead of the local `span` equivalent you might want to use a custom type just so the name makes it more obvious what's being done, e.g. `new (Realloc{old, count}, ac) T[n];`.
That example shows how for a type where default-initialization is not just uninitialized, it does what you want like `new` for the original allocation does, while for a type that can be uninitialized, that's still an option with no extra overhead.
And of course you can use it with constructor arguments in a situation where that makes sense.
Note that `realloc` is also sometimes used to trim an allocation to shorter than it was, and I'm not sure there's a way to do an analogous trick for that case such that destructors get run naturally.
================
Comment at: libc/src/__support/CPP/new.h:59
+ LIBC_INLINE static void *realloc(void *ptr, size_t s, AllocChecker &ac) {
+ void *mem = ::realloc(ptr, s);
+ ac = (mem != nullptr);
----------------
You might consider making this templated so `realloc<T>` takes and returns a `T*` and takes a count that it multiplies by `sizeof(T)`. That's also a good opportunity to `static_assert(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__);`.
That makes it more similar to `new` in terms of the invariants around static types and alignment constraints, though it's still importantly different for any type that doesn't have trivial (i.e. uninitialized) default construction.
================
Comment at: libc/src/__support/char_vector.h:37
if (cur_str != local_buffer)
- free(cur_str);
+ delete (cur_str);
}
----------------
Superfluous parens aren't usually used with `delete`.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D157653/new/
https://reviews.llvm.org/D157653
More information about the libc-commits
mailing list