On 5/26/26 12:17 PM, Jonathan Wakely wrote:
On Tue, 26 May 2026 at 16:13, Nathan Myers <[email protected]> wrote:

allocate_at_least rounds up the allocation request size to its
default alignment, which may be more than an integral multiple
of the object size requested. When the memory is freed, what the
container reports it is freeing differs from the amount that was
allocated. This patch rounds the request size back down to what
will be reported to the caller.

libstdc++-v3/ChangeLog:
         * include/bits/new_allocator.h (allocate_at_least): Reduce
         allocation to match what is reported.

The code change looks good. Can you also construct a test using
__gnu_test::tracker_allocator which fails without the fix?
Hmm, no, because the tracker_allocator only sees the return value from
__new_allocator::allocate_at_least which is correct (it's already been
adjusted to ignore the problematic extra bytes).

I think we'd need a testcase that replaces operator new / operator
delete and verifies that the numbers match. Could you try that?

I will essay it.

---
  libstdc++-v3/include/bits/new_allocator.h | 8 +++++---
  1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/libstdc++-v3/include/bits/new_allocator.h 
b/libstdc++-v3/include/bits/new_allocator.h
index 4524355a4a0..8d67b2d93fa 100644
--- a/libstdc++-v3/include/bits/new_allocator.h
+++ b/libstdc++-v3/include/bits/new_allocator.h
@@ -189,12 +189,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                 size_t __ask = (__need + __mask) & ~__mask;
                 // Avoid rounding up to and asking for 2^63 bytes (PR108377):
                 __ask -= __ask >> (__SIZE_WIDTH__ - 1);
-               auto* __p = static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__ask));
                 using _U8 = const unsigned char;
                 static_assert(sizeof(_Tp) <= ~_U8());
-               // Use 8-bit division for minimal latency:
+               // Use 8-bit arithmetic for minimal latency:
                 _U8 __spare = __ask - __need, __size = sizeof(_Tp);
-               return { __p , __n + __spare / __size };
+               __n   += __spare / __size;
+               __ask -= __spare % __size;
+               auto* __p = static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__ask));
+               return { __p, __n };
               }
           }
         return { allocate(__n), __n };
--
2.54.0



Reply via email to