YiFei
YiFei

Reputation: 1856

ASan new_delete_type_mismatch due to over alignment

Consider the following code snippet:

#include <new>
int main() {
    delete new (std::align_val_t(16)) char;
}

g++ 14.2.1 compiles it without warning (under -Wall -pedantic) and it runs without error. But when compiled with -fsanitize=address, ASan reports the following:

==17707==ERROR: AddressSanitizer: new-delete-type-mismatch on 0x503000000040 in thread T0:
  object passed to delete has wrong type:
  size of the allocated type:   1 bytes;
  size of the deallocated type: 1 bytes.
  alignment of the allocated type:   16 bytes;
  alignment of the deallocated type: default-aligned.
    #0 0x70912beff4f2 in operator delete(void*, unsigned long) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:164
    #1 0x6493bc2dd18d in main (/tmp/a.out+0x118d) (BuildId: e8f06d0aee8e301d7f1522801237096f3006c790)
    #2 0x70912b835487  (/usr/lib/libc.so.6+0x27487) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #3 0x70912b83554b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #4 0x6493bc2dd094 in _start (/tmp/a.out+0x1094) (BuildId: e8f06d0aee8e301d7f1522801237096f3006c790)

0x503000000040 is located 0 bytes inside of 1-byte region [0x503000000040,0x503000000041)
allocated by thread T0 here:
    #0 0x70912befe97a in operator new(unsigned long, std::align_val_t) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:107
    #1 0x6493bc2dd17b in main (/tmp/a.out+0x117b) (BuildId: e8f06d0aee8e301d7f1522801237096f3006c790)
    #2 0x70912b835487  (/usr/lib/libc.so.6+0x27487) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #3 0x70912b83554b in __libc_start_main (/usr/lib/libc.so.6+0x2754b) (BuildId: 695cfc6aac7d0f77bb7caba0ef01b2e868762b02)
    #4 0x6493bc2dd094 in _start (/tmp/a.out+0x1094) (BuildId: e8f06d0aee8e301d7f1522801237096f3006c790)

SUMMARY: AddressSanitizer: new-delete-type-mismatch /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:164 in operator delete(void*, unsigned long)

Is this a false positive by ASan? Or is it actually required to pair "aligned new" calls with "aligned delete" calls? Is it undefined behavior if not paired?

Edit: I suppose [new.delete] is relevant. But then my question becomes what is the best practice for freeing over-aligned memory (say, 32-byte aligned array of doubles for SIMD purposes)? Is it best to call operator delete explicitly?

Upvotes: 3

Views: 48

Answers (1)

3CxEZiVlQ
3CxEZiVlQ

Reputation: 38812

ASAN is right and reports the issue correctly. std::align_val_t:

Both new-expression and delete-expression, when used with objects whose alignment requirement is greater than __STDCPP_DEFAULT_NEW_ALIGNMENT__, pass that alignment requirement as an argument of type std::align_val_t to the selected allocation/deallocation function.

The correct usage:

::operator delete (new (std::align_val_t(16)) char, std::align_val_t(16));

https://godbolt.org/z/zrK1ffdEx

Upvotes: 0

Related Questions