I’ve been working on improving the aligned and sized allocation/deallocation checks in Valgrind, with a release due out in a few weeks.
I have some doubts as to what should be done in the case where an aligned new gets freed by a delete without alignment. 7.6.2.8 in C++20 says
[Note: If this results in a call to
a replaceable deallocation function, and either the first argument was not the result of a prior call to a
replaceable allocation function or the second or third argument was not the corresponding argument in said call, the behavior is undefined (17.6.2.1, 17.6.2.2). — end note]
That’s saying that if operator delete has a sized or aligned argument it must match the operator new for the pointer being deleted.
7.6.2.8 para 10.2 says that aligned delete is preferred for types with alignment.
I don’t see anything that requires pointers allocated with aligned new to be freed with aligned delete. If I understand correctly, C23 has similar rules for sized and aligned free, i.e., if you do use free_aligned_sized() the arguments need to match aligned_alloc() but you can still use plain free().
Here’s an example.
#include <new>
int main()
{
void *mem = operator new(1024U, static_cast<std::align_val_t>(256U));
operator delete(mem);
}
I don’t get any error with GCC ASAN or with Valgrind, but LLVM ASAN gives me
=================================================================
==47660==ERROR: AddressSanitizer: new-delete-type-mismatch on 0x61a000000100 in thread T0:
object passed to delete has wrong type:
alignment of the allocated type: 256 bytes;
alignment of the deallocated type: default-aligned.
#0 0x2d50dd in operator delete(void*) /usr/src/contrib/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:152:3
#1 0x2d6e03 in main /home/paulf/scratch/align/align.cpp:6:4
#2 0x23abcf in _start /usr/src/lib/csu/amd64/crt1_c.c:75:7
#3 0x8002fc007 (<unknown module>)
0x61a000000100 is located 0 bytes inside of 1024-byte region [0x61a000000100,0x61a000000500)
allocated by thread T0 here:
#0 0x2d4ca2 in operator new(unsigned long, std::align_val_t) /usr/src/contrib/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:107:3
#1 0x2d6df6 in main /home/paulf/scratch/align/align.cpp:5:16
#2 0x23abcf in _start /usr/src/lib/csu/amd64/crt1_c.c:75:7
#3 0x8002fc007 (<unknown module>)
SUMMARY: AddressSanitizer: new-delete-type-mismatch /usr/src/contrib/llvm-project/compiler-rt/lib/asan/asan_new_delete.cpp:152:3 in operator delete(void*)
==47660==HINT: if you don't care about these errors you may set ASAN_OPTIONS=new_delete_type_mismatch=0
==47660==ABORTING
Is LLVM being a little overzealous? I agree that aligned delete should be used, but I don’t think that the standard requires it.
Paul