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.

Reply via email to