Memory leak from wxDC constructor

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Memory leak from wxDC constructor

Frédéric
Hi,

I use a wxScreenDC as local variable in a function that I call just
once at the beginning of the program and sometimes get a leak error
from the sanitizer about the line where I construct the wxScreenDC.

Here is the code I use (simplified):
int void foo() {
  wxScreenDC dc; // this line is the origin of the memory leak
  dc.SetFont(wxFrame::GetClassDefaultAttributes().font);
  return dc.GetTextExtent("abc").GetWidth() / 3;
}

The documentation of wxDC::SetFont ( const wxFont &  font) says:
"If the argument is wxNullFont (or another invalid font; see
wxFont::IsOk), the current font is selected out of the device context
(leaving wxDC without any valid font), allowing the current font to be
destroyed safely."
Does that mean that we should always do it before destroying a wxDC?
Why then isn't it done in the destructor?

Unfortunately calling SetFon(wxNullFont) before the end of foo() does
not help (I can still have a memory leak).

Attached is the call stack.
I tried to make a very simplified sample but could not reproduce the bug then.

Kind regards,

F

--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.

To unsubscribe, send email to [hidden email]
or visit http://groups.google.com/group/wx-users

font-leak.txt.bz2 (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Memory leak from wxDC constructor

Vadim Zeitlin-4
On Tue, 23 Oct 2018 10:38:52 +0200 Frédéric wrote:

F> I use a wxScreenDC as local variable in a function that I call just
F> once at the beginning of the program and sometimes get a leak error
F> from the sanitizer about the line where I construct the wxScreenDC.
F>
F> Here is the code I use (simplified):
F> int void foo() {
F>   wxScreenDC dc; // this line is the origin of the memory leak
F>   dc.SetFont(wxFrame::GetClassDefaultAttributes().font);
F>   return dc.GetTextExtent("abc").GetWidth() / 3;
F> }

 wxFont objects are shared_ptr-like, i.e. they use reference counting
internally to refer to wxFontRefData they contain. This is obviously very
useful because fonts are often reused, but it does make tracking leaks much
harder because the allocation location almost invariably has nothing to do
with the place where the real leak happens. I.e. the live above is just
where this font gets created for the first time, but then it gets reused in
many other places and gets leaked in one of them -- but you don't know
where.

 Sometimes it's useful to put a conditional breakpoint on
wxObjectRefData::IncRef() and DecRef(), with the condition being "this ==
wxFontRefData-pointer-created-above" but it's probably going to be hit too
many times in this example. You can log a message showing the ref count and
continue, maybe this would allow you to identify the place where the ref
count gets bumped up without the matching decrement.

 Another advice is to check if you have any other memory leaks because it's
pretty unusual to allocate just a wxFont, typically the leaked wxFont is
part of another object, which is leaked too. So if you have any other
leaks, try fixing them first and maybe this one will disappear as well.

F> The documentation of wxDC::SetFont ( const wxFont &  font) says:
F> "If the argument is wxNullFont (or another invalid font; see
F> wxFont::IsOk), the current font is selected out of the device context
F> (leaving wxDC without any valid font), allowing the current font to be
F> destroyed safely."
F> Does that mean that we should always do it before destroying a wxDC?

 No, you don't need to do this explicitly.

F> Why then isn't it done in the destructor?

 It is.

 Regards,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
               http://www.tt-solutions.com/

attachment0 (203 bytes) Download Attachment