[PATCH v4] libstdc++: Use allocate_at_least in vector, string (P0401) [PR118030]
Tomasz Kaminski
tkaminsk@redhat.com
Tue May 26 15:26:06 GMT 2026
For object with size __s == 12 and __n==3, we allocate 36 bytes.
But, if new keeps chunks that are multiples of
__STDCPP_DEFAULT_NEW_ALIGNMENT__ (16),
we could ask for 48 bytes, and get four elements.
On Tue, May 26, 2026 at 2:55 PM Jonathan Wakely <jwakely@redhat.com> wrote:
> On Tue, 26 May 2026 at 13:27, Nathan Myers <ncm@cantrip.org> wrote:
> >
> > On 5/26/26 8:22 AM, Jonathan Wakely wrote:
> > > On Tue, 26 May 2026 at 12:05, Stephan Bergmann <sberg.fun@gmail.com>
> wrote:
> > >>
> > >> On 5/26/26 09:04, Stephan Bergmann wrote:
> > >> [...]
> > >>> Oh, sorry, my bad: This was an incremental build of GCC. With a
> from-
> > >>> scratch one, everything's fine again!
> > >>
> > >> What still fails after a from scratch build, though, is:
> > >>
> > >>> $ cat test.cc
> > >>> #include <vector>
> > >>> int main() {
> > >>> struct S { char a[12]; };
> > >>> std::vector<S> v;
> > >>> v.reserve(1);
> > >>> }
> > >>
> > >>> $ g++ -std=c++23 -fsanitize=address test.cc && ./a.out
> > >>> =================================================================
> > >>> ==1207948==ERROR: AddressSanitizer: new-delete-type-mismatch on
> 0x7c12b93e0010 in thread T0:
> > >>> object passed to delete has wrong type:
> > >>> size of the allocated type: 16 bytes;
> > >>> size of the deallocated type: 12 bytes.
> > >>> #0 0x7ff2ba8f13bf in operator delete(void*, unsigned long)
> (/lib64/libasan.so.8+0xf13bf) (BuildId:
> 5395ec74f54d9ec7bf97c06583dd39a96c230822)
> > >>> #1 0x00000040131a in
> std::__new_allocator<main::S>::deallocate(main::S*, unsigned long)
> (/home/sberg/a.out+0x40131a)
> > >>> #2 0x000000400b79 in std::_Vector_base<main::S,
> std::allocator<main::S> >::_M_deallocate(main::S*, unsigned long)
> (/home/sberg/a.out+0x400b79)
> > >>> #3 0x000000400790 in std::_Vector_base<main::S,
> std::allocator<main::S> >::~_Vector_base() (/home/sberg/a.out+0x400790)
> > >>> #4 0x000000400839 in std::vector<main::S,
> std::allocator<main::S> >::~vector() (/home/sberg/a.out+0x400839)
> > >>> #5 0x000000400653 in main (/home/sberg/a.out+0x400653)
> > >>> #6 0x7ff2ba208680 in __libc_start_call_main
> (/lib64/libc.so.6+0x3680) (BuildId:
> d597f1cdc38bc65e2fff68bda171301550e79d0c)
> > >>> #7 0x7ff2ba208797 in __libc_start_main@GLIBC_2.2.5
> (/lib64/libc.so.6+0x3797) (BuildId:
> d597f1cdc38bc65e2fff68bda171301550e79d0c)
> > >>> #8 0x000000400474 in _start (/home/sberg/a.out+0x400474)
> > >>>
> > >>> 0x7c12b93e0010 is located 0 bytes inside of 16-byte region
> [0x7c12b93e0010,0x7c12b93e0020)
> > >>> allocated by thread T0 here:
> > >>> #0 0x7ff2ba8f04ff in operator new(unsigned long)
> (/lib64/libasan.so.8+0xf04ff) (BuildId:
> 5395ec74f54d9ec7bf97c06583dd39a96c230822)
> > >>> #1 0x0000004013c1 in
> std::__new_allocator<main::S>::allocate_at_least(unsigned long)
> (/home/sberg/a.out+0x4013c1)
> > >>> #2 0x000000400d0e in std::_Vector_base<main::S,
> std::allocator<main::S> >::_M_allocate_at_least(unsigned long)
> (/home/sberg/a.out+0x400d0e)
> > >>> #3 0x0000004009c0 in std::vector<main::S,
> std::allocator<main::S> >::reserve(unsigned long)
> (/home/sberg/a.out+0x4009c0)
> > >>> #4 0x000000400647 in main (/home/sberg/a.out+0x400647)
> > >>> #5 0x7ff2ba208680 in __libc_start_call_main
> (/lib64/libc.so.6+0x3680) (BuildId:
> d597f1cdc38bc65e2fff68bda171301550e79d0c)
> > >>> #6 0x7ff2ba208797 in __libc_start_main@GLIBC_2.2.5
> (/lib64/libc.so.6+0x3797) (BuildId:
> d597f1cdc38bc65e2fff68bda171301550e79d0c)
> > >>> #7 0x000000400474 in _start (/home/sberg/a.out+0x400474)
> > >>>
> > >>> SUMMARY: AddressSanitizer: new-delete-type-mismatch
> (/home/sberg/a.out+0x40131a) in
> std::__new_allocator<main::S>::deallocate(main::S*, unsigned long)
> > >>> ==1207948==HINT: if you don't care about these errors you may set
> ASAN_OPTIONS=new_delete_type_mismatch=0
> > >>> ==1207948==ABORTING
> > >>
> > >
> > > Nathan, please take a look.
> > >
> > > __new_allocator::allocate_at_least is rounding up to get __ask=16
> > > which makes no sense for an allocation of a single 12-byte object. We
> > > can't make use of extra bytes if the size we round up is less than
> > > sizeof(T).
> >
> > Thank you, you are right. Patch coming.
>
>
> It should probably depend on:
>
> sizeof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__ / 2
>
> because if adding an extra sizeof(T) bytes would take us over the
> default alignment, we don't want to do it.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260526/7ba24867/attachment-0001.htm>
More information about the Libstdc++
mailing list