https://bugs.kde.org/show_bug.cgi?id=517126

            Bug ID: 517126
           Summary: Mismatched frees with ICF
    Classification: Developer tools
           Product: valgrind
      Version First 3.27 GIT
       Reported In:
          Platform: unspecified
                OS: All
            Status: REPORTED
          Severity: normal
          Priority: NOR
         Component: memcheck
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

ICF is Identical Code Folding, a feature available with lld and gold but not
GNU BFD ld.

With this feature the linker can eliminate functions that use identical machine
code. Unfortunately for us that can include overloads of operator delete.

I don't think that we can do anything about this. Could DWARF help? At the
moment I think that I'll just add a FAQ entry along the lines "don't use ICF,
if you must use it then either suppress any errors that it causes or use the
option --show-mismatched-frees=no".

Here is an example

#include <map>
#include <new>
#include <cstddef>
#include <iostream>

struct StuffA {
    char* alignas(64) d;
    StuffA() : d(new char[42]) {}
    ~StuffA() { delete [] d;}
    StuffA(const StuffA& thing) {
        d = new char[42];
    }
    StuffA& operator=(const StuffA& other) {
        // do nothing, just pretend they were copied
        return *this;
    }
};

struct StuffB {
    char* d;
    StuffB() : d(new char[42]) {}
    ~StuffB() { delete [] d;}
    StuffB(const StuffB& thing) {
        d = new char[42];
    }
    StuffB& operator=(const StuffB& other) {
        // do nothing, just pretend they were copied
        return *this;
    }

};


struct alignas(64) BigAligned {
    int payload;
    StuffA a;
    BigAligned(int v = 0) : payload(v) {}
};

bool operator<(const BigAligned& a, const BigAligned& b) { return a.payload <
b.payload; }

struct Normal {
    int payload;
    StuffB b;
    Normal(int v = 0) : payload(v) {}
};

bool operator<(const Normal& a, const Normal& b) { return a.payload <
b.payload; }

int main() {
    std::map<BigAligned, BigAligned> m;
    std::map<Normal, Normal> n;

    // Insert some elements — std::map allocates nodes internally
    for (int i = 0; i < 10; ++i) {
        m.emplace(BigAligned{i}, BigAligned{i * 2});
    }

    // Insert some elements — std::map allocates nodes internally
    for (int i = 0; i < 10; ++i) {
        n.emplace(Normal{i}, Normal{i * 2});
    }

    // Erase elements — this forces std::map to call delete on node pointers
    for (int i = 0; i < 10; ++i) {
        m.erase(BigAligned{i});
    }

    // Erase elements — this forces std::map to call delete on node pointers
    for (int i = 0; i < 10; ++i) {
        n.erase(Normal{i});
    }

    return 0;
}

Compile with
g++ -std=c++20 -O2 -Wl,--icf=all map_aligned.cpp -o map_aligned -fuse-ld=lld -g
-Wl,-rpath,$HOME/tools/gcc/lib64 -static-libstdc++

That gives erorrs like

==2263== Mismatched free() / delete / delete []
==2263==    at 0x404273C: operator delete[](void*) (vg_replace_malloc.c:1362)
==2263==    by 0x22E812: deallocate (new_allocator.h:172)
==2263==    by 0x22E812: deallocate (allocator.h:215)
==2263==    by 0x22E812: deallocate (alloc_traits.h:649)
==2263==    by 0x22E812: _M_put_node (stl_tree.h:1191)
==2263==    by 0x22E812: _M_drop_node (stl_tree.h:1274)
==2263==    by 0x22E812: _M_erase_aux (stl_tree.h:3116)
==2263==    by 0x22E812: _M_erase_aux (stl_tree.h:3130)
==2263==    by 0x22E812: erase (stl_tree.h:3141)
==2263==    by 0x22E812: erase (stl_map.h:1159)
==2263==    by 0x22E812: main (map_aligned.cpp:71)
==2263==  Address 0x519e6e0 is 0 bytes inside a block of size 64 alloc'd
==2263==    at 0x403CED8: operator new(unsigned long) (vg_replace_malloc.c:501)
==2263==    by 0x22E213: allocate (new_allocator.h:151)
==2263==    by 0x22E213: allocate (allocator.h:203)
==2263==    by 0x22E213: allocate (alloc_traits.h:614)
==2263==    by 0x22E213: _M_get_node (stl_tree.h:1170)
==2263==    by 0x22E213: _M_create_node<Normal, Normal> (stl_tree.h:1253)
==2263==    by 0x22E213: _Auto_node<Normal, Normal> (stl_tree.h:2285)
==2263==    by 0x22E213: std::_Rb_tree_iterator<std::pair<Normal const, Normal>
> std::_Rb_tree<Normal, std::pair<Normal const, Normal>,
std::_Select1st<std::pair<Normal const, Normal> >, std::less<Normal>,
std::allocator<std::pair<Normal const, Normal> >
>::_M_emplace_hint_unique<Normal,
Normal>(std::_Rb_tree_const_iterator<std::pair<Normal const, Normal> >,
Normal&&, Normal&&) (stl_tree.h:3084)
==2263==    by 0x22E605: emplace_hint<Normal, Normal> (stl_map.h:663)
==2263==    by 0x22E605: emplace<Normal, Normal> (stl_map.h:624)
==2263==    by 0x22E605: main (map_aligned.cpp:61)

(I tried to generate some mismatched aligned new [] / delete [] errors but no
luck).

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to