https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86385
--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> --- Reduced slightly: struct A { int* a; A(int a) : a(new int(a)) {} ~A() { delete a; } A(const A&) = delete; A(A&& other) { a = other.a; other.a = 0; }; operator bool() { return true; } }; A makeA(int x) { return A(x); } int main() { makeA(42) ?: makeA(-1); } Valgrind shows: ==26332== Memcheck, a memory error detector ==26332== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==26332== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==26332== Command: ./a.out ==26332== ==26332== Invalid free() / delete / delete[] / realloc() ==26332== at 0x4C2E1E8: operator delete(void*) (vg_replace_malloc.c:576) ==26332== by 0x40078A: A::~A() (tern.cc:4) ==26332== by 0x400714: main (tern.cc:15) ==26332== Address 0x5ae4c80 is 0 bytes inside a block of size 4 free'd ==26332== at 0x4C2E1E8: operator delete(void*) (vg_replace_malloc.c:576) ==26332== by 0x40078A: A::~A() (tern.cc:4) ==26332== by 0x400708: main (tern.cc:15) ==26332== Block was alloc'd at ==26332== at 0x4C2D1CA: operator new(unsigned long) (vg_replace_malloc.c:334) ==26332== by 0x400756: A::A(int) (tern.cc:3) ==26332== by 0x4006B1: makeA(int) (tern.cc:12) ==26332== by 0x4006D1: main (tern.cc:15) ==26332== ==26332== ==26332== HEAP SUMMARY: ==26332== in use at exit: 0 bytes in 0 blocks ==26332== total heap usage: 2 allocs, 3 frees, 72,708 bytes allocated ==26332== ==26332== All heap blocks were freed -- no leaks are possible ==26332== ==26332== For counts of detected and suppressed errors, rerun with: -v ==26332== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) Asan shows: ================================================================= ==26649==ERROR: AddressSanitizer: attempting double-free on 0x602000000010 in thread T0: #0 0x7f81bb1dc2c8 in operator delete(void*, unsigned long) /home/jwakely/src/gcc/gcc/libsanitizer/asan/asan_new_delete.cc:151 #1 0x400d4b in A::~A() /tmp/tern.cc:4 #2 0x400bdc in main /tmp/tern.cc:15 #3 0x7f81ba478f29 in __libc_start_main ../csu/libc-start.c:308 #4 0x400989 in _start (/tmp/a.out+0x400989) 0x602000000010 is located 0 bytes inside of 4-byte region [0x602000000010,0x602000000014) freed by thread T0 here: #0 0x7f81bb1dc2c8 in operator delete(void*, unsigned long) /home/jwakely/src/gcc/gcc/libsanitizer/asan/asan_new_delete.cc:151 #1 0x400d4b in A::~A() /tmp/tern.cc:4 #2 0x400bbf in main /tmp/tern.cc:15 #3 0x7f81ba478f29 in __libc_start_main ../csu/libc-start.c:308 previously allocated by thread T0 here: #0 0x7f81bb1daed0 in operator new(unsigned long) /home/jwakely/src/gcc/gcc/libsanitizer/asan/asan_new_delete.cc:90 #1 0x400c9e in A::A(int) /tmp/tern.cc:3 #2 0x400a51 in makeA(int) /tmp/tern.cc:12 #3 0x400b25 in main /tmp/tern.cc:15 #4 0x7f81ba478f29 in __libc_start_main ../csu/libc-start.c:308 SUMMARY: AddressSanitizer: double-free /home/jwakely/src/gcc/gcc/libsanitizer/asan/asan_new_delete.cc:151 in operator delete(void*, unsigned long) ==26649==ABORTING Maybe the object is being copied by an implicitly-defined copy constructor, but that's meant to be deleted and overload resolution should have used the move constructor.