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

            Bug ID: 520170
           Summary: valgrind reports Mismatched free() / delete / delete
                    [], but it doesn't appear to be mismatched
    Classification: Developer tools
           Product: valgrind
      Version First 3.23.0
       Reported In:
          Platform: Flatpak
                OS: Linux
            Status: REPORTED
          Severity: normal
          Priority: NOR
         Component: memcheck
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

DESCRIPTION

I'm trying to run GNOME Builder under valgrind 3.27.0 because I strongly
suspect there is a memory corruption issue somewhere in vte. I think valgrind
might be printing false positive complaints about mismatched
free/delete/delete[]. I've been doing some squinting, and it doesn't appear to
be a mismatch.

According to valgrind, the allocation occurs here:
https://github.com/gcc-mirror/gcc/blob/5115c7e447fc07457443df874bf57840e8316d5f/libstdc%2B%2B-v3/include/bits/new_allocator.h#L151

And the free is here:
https://github.com/gcc-mirror/gcc/blob/5115c7e447fc07457443df874bf57840e8316d5f/libstdc%2B%2B-v3/include/bits/new_allocator.h#L172

It uses _GLIBCXX_OPERATOR_NEW and _GLIBCXX_OPERATOR_DELETE, but those are just
defined to ::operator new and ::operator delete, so it certainly appears to be
a match. And yet, there is definitely a mismatch once it reaches
vg_replace_malloc.c. It's weird that the code in libstdc++'s new_allocator.h
appears to call operator new, not operator new[], but it actually calls
valgrind's operator new[]. That's pretty strange? I'm confused.


STEPS TO REPRODUCE

$ flatpak run -d --command=bash org.gnome.Builder.Devel
[📦 org.gnome.Builder.Devel ~]$ valgrind --track-origins=yes --num-callers=20
gnome-builder


OBSERVED RESULT

valgrind will print lots of complaints when Builder is started. The first one
looks like this:

==84== Mismatched free() / delete / delete []
==84==    at 0x4FE6B1D: free_sized (vg_replace_malloc.c:996)
==84==    by 0x68D5B63: deallocate (new_allocator.h:172)
==84==    by 0x68D5B63: deallocate (allocator.h:215)
==84==    by 0x68D5B63: deallocate (alloc_traits.h:649)
==84==    by 0x68D5B63: _M_deallocate (stl_vector.h:396)
==84==    by 0x68D5B63: _M_deallocate (stl_vector.h:392)
==84==    by 0x68D5B63: ~_Guard_alloc (stl_vector.h:1883)
==84==    by 0x68D5B63: _M_realloc_append<int, unsigned int,
vte::property::Type, vte::property::Flags, const
std::function<std::optional<std::variant<std::monostate, bool, long int, long
unsigned int, double, vte::color::rgba_base<float>, vte::uuid,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>
>, std::pair<std::unique_ptr<_GUri, vte::FreeableDeleter<_GUri> >,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >
>, std::unique_ptr<_cairo_surface, vte::FreeableDeleter<_cairo_surface> > >
>(std::basic_string_view<char, std::char_traits<char> >)> > (vector.tcc:640)
==84==    by 0x68D5B63: emplace_back<int, unsigned int, vte::property::Type,
vte::property::Flags, const
std::function<std::optional<std::variant<std::monostate, bool, long int, long
unsigned int, double, vte::color::rgba_base<float>, vte::uuid,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>
>, std::pair<std::unique_ptr<_GUri, vte::FreeableDeleter<_GUri> >,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >
>, std::unique_ptr<_cairo_surface, vte::FreeableDeleter<_cairo_surface> > >
>(std::basic_string_view<char, std::char_traits<char> >)> > (vector.tcc:123)
==84==    by 0x68D5B63:
vte::property::Registry::install_many(std::initializer_list<vte::property::Registry::Property>)
(properties.hh:252)
==84==    by 0x68D74D4: vte::terminal::TermpropsRegistry::TermpropsRegistry()
(termpropsregistry.cc:199)
==84==    by 0x68D7B93: termprops_registry (termpropsregistry.cc:289)
==84==    by 0x68D7B93: vte::terminal::termprops_registry()
(termpropsregistry.cc:287)
==84==    by 0x68F3D8D:
vte::terminal::Terminal::Terminal(vte::platform::Widget*, _VteTerminal*)
(vte.cc:8415)
==84==    by 0x6929A06: vte::platform::Widget::Widget(_VteTerminal*)
(widget.cc:664)
==84==    by 0x68FBAB5: _Construct<vte::platform::Widget, _VteTerminal*&>
(stl_construct.h:133)
==84==    by 0x68FBAB5: construct<vte::platform::Widget, _VteTerminal*&>
(alloc_traits.h:805)
==84==    by 0x68FBAB5: _Sp_counted_ptr_inplace<_VteTerminal*&>
(shared_ptr_base.h:606)
==84==    by 0x68FBAB5: __shared_count<vte::platform::Widget,
std::allocator<void>, _VteTerminal*&> (shared_ptr_base.h:969)
==84==    by 0x68FBAB5: __shared_ptr<std::allocator<void>, _VteTerminal*&>
(shared_ptr_base.h:1719)
==84==    by 0x68FBAB5: shared_ptr<std::allocator<void>, _VteTerminal*&>
(shared_ptr.h:463)
==84==    by 0x68FBAB5: make_shared<vte::platform::Widget, _VteTerminal*&>
(shared_ptr.h:1008)
==84==    by 0x68FBAB5: VteTerminalPrivate (vtegtk.cc:137)
==84==    by 0x68FBAB5: vte_terminal_init(_VteTerminal*) (vtegtk.cc:184)
==84==    by 0x542468A: g_type_create_instance (gtype.c:1894)
==84==    by 0x54078B3: g_object_new_internal.part.0 (gobject.c:2671)
==84==    by 0x5408F6D: g_object_new_internal (gobject.c:2668)
==84==    by 0x5408F6D: g_object_new_with_properties (gobject.c:2833)
==84==    by 0x5409FD0: g_object_new (gobject.c:2481)
==84==    by 0x5707B41: _gtk_builder_construct (gtkbuilder.c:1021)
==84==    by 0x5709C84: builder_construct (gtkbuilderparser.c:474)
==84==    by 0x570C485: parse_custom (gtkbuilderparser.c:1849)
==84==    by 0x570C485: start_element (gtkbuilderparser.c:1962)
==84==    by 0x58F4A21: replay_start_element (gtkbuilderprecompile.c:636)
==84==    by 0x58F52A0: _gtk_buildable_parser_replay_precompiled
(gtkbuilderprecompile.c:739)
==84==    by 0x570D949: gtk_buildable_parse_context_parse
(gtkbuilderparser.c:191)
==84==    by 0x570D949: _gtk_builder_parser_parse_buffer
(gtkbuilderparser.c:2349)
==84==    by 0x570501D: gtk_builder_extend_with_template (gtkbuilder.c:1583)
==84==    by 0x58C5EBD: gtk_widget_init_template (gtkwidget.c:11444)
==84==    by 0x444206B: gbp_vcsui_clone_page_init (gbp-vcsui-clone-page.c:437)
==84==  Address 0x1b841470 is 0 bytes inside a block of size 48 alloc'd
==84==    at 0x4FE55F3: operator new[](unsigned long) (vg_replace_malloc.c:717)
==84==    by 0x68D596E: allocate (new_allocator.h:151)
==84==    by 0x68D596E: allocate (allocator.h:203)
==84==    by 0x68D596E: allocate (alloc_traits.h:614)
==84==    by 0x68D596E: _M_allocate (stl_vector.h:387)
==84==    by 0x68D596E: _M_realloc_append<int, unsigned int,
vte::property::Type, vte::property::Flags, const
std::function<std::optional<std::variant<std::monostate, bool, long int, long
unsigned int, double, vte::color::rgba_base<float>, vte::uuid,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>
>, std::pair<std::unique_ptr<_GUri, vte::FreeableDeleter<_GUri> >,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >
>, std::unique_ptr<_cairo_surface, vte::FreeableDeleter<_cairo_surface> > >
>(std::basic_string_view<char, std::char_traits<char> >)> > (vector.tcc:572)
==84==    by 0x68D596E: emplace_back<int, unsigned int, vte::property::Type,
vte::property::Flags, const
std::function<std::optional<std::variant<std::monostate, bool, long int, long
unsigned int, double, vte::color::rgba_base<float>, vte::uuid,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>
>, std::pair<std::unique_ptr<_GUri, vte::FreeableDeleter<_GUri> >,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >
>, std::unique_ptr<_cairo_surface, vte::FreeableDeleter<_cairo_surface> > >
>(std::basic_string_view<char, std::char_traits<char> >)> > (vector.tcc:123)
==84==    by 0x68D596E:
vte::property::Registry::install_many(std::initializer_list<vte::property::Registry::Property>)
(properties.hh:252)
==84==    by 0x68D74D4: vte::terminal::TermpropsRegistry::TermpropsRegistry()
(termpropsregistry.cc:199)
==84==    by 0x68D7B93: termprops_registry (termpropsregistry.cc:289)
==84==    by 0x68D7B93: vte::terminal::termprops_registry()
(termpropsregistry.cc:287)
==84==    by 0x68F3D8D:
vte::terminal::Terminal::Terminal(vte::platform::Widget*, _VteTerminal*)
(vte.cc:8415)
==84==    by 0x6929A06: vte::platform::Widget::Widget(_VteTerminal*)
(widget.cc:664)
==84==    by 0x68FBAB5: _Construct<vte::platform::Widget, _VteTerminal*&>
(stl_construct.h:133)
==84==    by 0x68FBAB5: construct<vte::platform::Widget, _VteTerminal*&>
(alloc_traits.h:805)
==84==    by 0x68FBAB5: _Sp_counted_ptr_inplace<_VteTerminal*&>
(shared_ptr_base.h:606)
==84==    by 0x68FBAB5: __shared_count<vte::platform::Widget,
std::allocator<void>, _VteTerminal*&> (shared_ptr_base.h:969)
==84==    by 0x68FBAB5: __shared_ptr<std::allocator<void>, _VteTerminal*&>
(shared_ptr_base.h:1719)
==84==    by 0x68FBAB5: shared_ptr<std::allocator<void>, _VteTerminal*&>
(shared_ptr.h:463)
==84==    by 0x68FBAB5: make_shared<vte::platform::Widget, _VteTerminal*&>
(shared_ptr.h:1008)
==84==    by 0x68FBAB5: VteTerminalPrivate (vtegtk.cc:137)
==84==    by 0x68FBAB5: vte_terminal_init(_VteTerminal*) (vtegtk.cc:184)
==84==    by 0x542468A: g_type_create_instance (gtype.c:1894)
==84==    by 0x54078B3: g_object_new_internal.part.0 (gobject.c:2671)
==84==    by 0x5408F6D: g_object_new_internal (gobject.c:2668)
==84==    by 0x5408F6D: g_object_new_with_properties (gobject.c:2833)
==84==    by 0x5409FD0: g_object_new (gobject.c:2481)
==84==    by 0x5707B41: _gtk_builder_construct (gtkbuilder.c:1021)
==84==    by 0x5709C84: builder_construct (gtkbuilderparser.c:474)
==84==    by 0x570C485: parse_custom (gtkbuilderparser.c:1849)
==84==    by 0x570C485: start_element (gtkbuilderparser.c:1962)
==84==    by 0x58F4A21: replay_start_element (gtkbuilderprecompile.c:636)
==84==    by 0x58F52A0: _gtk_buildable_parser_replay_precompiled
(gtkbuilderprecompile.c:739)
==84==    by 0x570D949: gtk_buildable_parse_context_parse
(gtkbuilderparser.c:191)
==84==    by 0x570D949: _gtk_builder_parser_parse_buffer
(gtkbuilderparser.c:2349)
==84==    by 0x570501D: gtk_builder_extend_with_template (gtkbuilder.c:1583)
==84==    by 0x58C5EBD: gtk_widget_init_template (gtkwidget.c:11444)
==84==    by 0x444206B: gbp_vcsui_clone_page_init (gbp-vcsui-clone-page.c:437)


EXPECTED RESULT

Don't complain unless there is an actual mismatch.

SOFTWARE/OS VERSIONS

I'm using GNOME Nightly runtime, based on freedesktop-sdk 25.08. valgrind is
3.27.0 and libstdc++ is from GCC 15.2.0.

ADDITIONAL INFORMATION

The actual definition of _GLIBCXX_OPERATOR_NEW and _GLIBCXX_OPERATOR_DELETE is
a little more complicated:

#if __has_builtin(__builtin_operator_new) >= 201802L
# define _GLIBCXX_OPERATOR_NEW __builtin_operator_new
# define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete
#else
# define _GLIBCXX_OPERATOR_NEW ::operator new
# define _GLIBCXX_OPERATOR_DELETE ::operator delete
#endif

So I built a simple test program with GCC:

#if __has_builtin(__builtin_operator_new) >= 201802L
#error Got builtin op!
#else
#error No builtin op!
#endif

And it says "No builtin op," so I assume those are only used for Clang.

I also wondered: is it possible that the memory was allocated in code built by
one compiler, and deallocated in code built by a different compiler, such that
the definitions really do become mismatched? But in this example, both
allocation and deallocation occur in vte's termpropsregistry.cc, so it's the
same source code file.

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

Reply via email to