Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Detecting memory leaks.

by Steve_BZ (Chaplain)
on May 04, 2015 at 14:28 UTC ( [id://1125580]=perlquestion: print w/replies, xml ) Need Help??

Steve_BZ has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

I have a fairly mature but functionally independent, piece of code that precedes a call to a video player in wxPerl.

When this code is not called the video (gstreamer) never crashes. When the code is called the video crashes occasionally, maybe 10% of the time.

This issue is of fairly long standing, but because it is sporadic, no-one is quite sure when it started.

While watching this happen in a performance monitor, I noticed that the memory utilisation was not stable and that it gradually increased over time. I tried tracking this through Valgrind and Valgrind showed some kilobytes of memory leaks, but didn't specify when they occurred (ie in real time). Just at the end in the leak summary.

I have been using Memory::Usage as shown in http://perlmaven.com/eliminate-circular-reference-memory-leak-using-weaken to try to find trhe leak, but without much success. Every time I think I have found it, I modify the code only to find the Memory 'diff' move down the script.

Here is a sample of the output:

time vsz ( diff) rss ( diff) shared ( diff) code ( diff) + data ( diff) 0 774028 ( 774028) 193524 ( 193524) 43648 ( 43648) 8 ( + 8) 368928 ( 368928) before i_Booking->new 0 774028 ( 0) 193524 ( 0) 43648 ( 0) 8 ( +0) 368928 ( 0) after i_Booking tbl_patient_exam 0 774028 ( 0) 193524 ( 0) 43648 ( 0) 8 ( +0) 368928 ( 0) before i_Booking SetScreenHeader 0 774028 ( 0) 193524 ( 0) 43648 ( 0) 8 ( +0) 368928 ( 0) after i_Booking SetScreenHeader 0 774028 ( 0) 193524 ( 0) 43648 ( 0) 8 ( +0) 368928 ( 0) after i_Booking set focus 0 774028 ( 0) 193524 ( 0) 43648 ( 0) 8 ( +0) 368928 ( 0) before i_Booking i_staticText 1 0 774028 ( 0) 193524 ( 0) 43648 ( 0) 8 ( +0) 368928 ( 0) after i_Booking i_staticText 1 0 774648 ( 620) 193524 ( 0) 43648 ( 0) 8 ( +0) 368928 ( 0) before i_Booking Ctl_Booking_Referring_Doctor_Ref +_4_Lbl 0 774648 ( 0) 193524 ( 0) 43648 ( 0) 8 ( +0) 368928 ( 0) before i_Booking i_staticText 2 0 774648 ( 0) 193524 ( 0) 43648 ( 0) 8 ( +0) 368928 ( 0) after i_Booking i_staticText 2 0 774648 ( 0) 193800 ( 276) 43924 ( 276) 8 ( +0) 368928 ( 0) before i_Booking health plan providor 0 774648 ( 0) 193800 ( 0) 43924 ( 0) 8 ( +0) 368928 ( 0) at i_Booking mid point 0 774648 ( 0) 193804 ( 4) 43924 ( 0) 8 ( +0) 368928 ( 0) at i_Booking DatePickerCtrl 0 774780 ( 132) 193932 ( 128) 43924 ( 0) 8 ( +0) 369060 ( 132) at i_Booking Examining Doctor Search 0 774912 ( 132) 194172 ( 240) 43924 ( 0) 8 ( +0) 369192 ( 132) at i_Booking Patient details 0 774912 ( 0) 194172 ( 0) 43924 ( 0) 8 ( +0) 369192 ( 0) before i_Booking $loc_window_layout->SetFooter 0 774912 ( 0) 194172 ( 0) 43924 ( 0) 8 ( +0) 369192 ( 0) after i_Booking $loc_window_layout->SetFooter 0 774912 ( 0) 194172 ( 0) 43924 ( 0) 8 ( +0) 369192 ( 0) at i_Booking exit

I am suspicious of a number of pieces of code, but like bubbles in the wall-paper the bubble just moves when I press it. For instance in the above output, we see :

0 774648 ( 620) 193524 ( 0) 43648 ( 0) 8 ( +0) 368928 ( 0) before i_Booking Ctl_Booking_Referring_Doctor_Ref
The total code between this line and the previous output is shown here, together with the surrounding lines:
# Referring Dr details from Dr file $booking_dlg->{Ctl_Booking_Referring_Doctor_Lbl} = Wx::StaticText- +>new($booking_dlg->{booking_main}, wxID_ANY, __t('Referring Doctor'), + wxDefaultPosition, wxDefaultSize, ); $mu->record('before i_Booking i_staticText 1'); $booking_dlg->{Ctl_Booking_Referring_Doctor_Txt} = i_staticText->n +ew($booking_dlg->{booking_main}, wxID_ANY, "", wxDefaultPosition, wxD +efaultSize, ); $mu->record('after i_Booking i_staticText 1'); $booking_dlg->{Ctl_Booking_Referring_Doctor_Txt}->SetFont(Wx::Font +->new($gl_cfg->{client_point_size}, wxMODERN, wxFONTSTYLE_ITALIC, wxF +ONTWEIGHT_BOLD, 0, $gl_cfg->{client_font})); $mu->record('before i_Booking Ctl_Booking_Referring_Doctor_Ref_4_L +bl'); $booking_dlg->{Ctl_Booking_Referring_Doctor_Ref_4_Lbl} = Wx::Stati +cText->new($booking_dlg->{booking_main}, wxID_ANY, __t("Ref 4"), wxDe +faultPosition, wxDefaultSize, ); $mu->record('before i_Booking i_staticText 2'); $booking_dlg->{Ctl_Booking_Referring_Doctor_Ref_4_Txt} = i_staticT +ext->new($booking_dlg->{booking_main}, wxID_ANY, "", wxDefaultPositio +n, __xy_size(100), ); $mu->record('after i_Booking i_staticText 2'); $booking_dlg->{Ctl_Booking_Referring_Doctor_Ref_4_Txt}->SetFont(Wx +::Font->new($gl_cfg->{client_point_size}, wxMODERN, wxFONTSTYLE_ITALI +C, wxFONTWEIGHT_BOLD, 0, $gl_cfg->{client_font}));

But really the code here looks quite innocent.

Any ideas would be welcome.

Regards

Steve.

Replies are listed 'Best First'.
Re: Detecting memory leaks.
by BrowserUk (Patriarch) on May 04, 2015 at 14:44 UTC
    Wx::Font->new($gl_cfg->{client_point_size}, wxMODERN, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_BOLD, 0, $gl_cfg->{client_font})

    620 bytes doesn't seem like a lot for a new font.

    Is it really necessary to create a new font each time? Couldn't you create the font once and reference it when you need it?

    Ditto other things.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
    In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked

      Hi BrowserUK,

      Thanks for that. A sensible suggestion. I just did that and made a global replace. I also moved the Wx::Font line before the rest of the code, like this:

      my $loc_font_wx=Wx::Font->new($gl_cfg->{client_point_size}, wxMODE +RN, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_BOLD, 0, $gl_cfg->{client_font}) +; $mu->record('after i_Booking set focus'); # Referring Dr details from Dr file $booking_dlg->{Ctl_Booking_Referring_Doctor_Lbl} = Wx::StaticText- +>new($booking_dlg->{booking_main}, wxID_ANY, __t('Referring Doctor'), + wxDefaultPosition, wxDefaultSize, ); $mu->record('before i_Booking i_staticText 1'); $booking_dlg->{Ctl_Booking_Referring_Doctor_Txt} = i_staticText->n +ew($booking_dlg->{booking_main}, wxID_ANY, "", wxDefaultPosition, wxD +efaultSize, ); $mu->record('after i_Booking i_staticText 1'); $booking_dlg->{Ctl_Booking_Referring_Doctor_Txt}->SetFont($loc_fon +t_wx); $mu->record('before i_Booking Ctl_Booking_Referring_Doctor_Ref_4_L +bl'); $booking_dlg->{Ctl_Booking_Referring_Doctor_Ref_4_Lbl} = Wx::Stati +cText->new($booking_dlg->{booking_main}, wxID_ANY, __t("Ref 4"), wxDe +faultPosition, wxDefaultSize, ); $mu->record('before i_Booking i_staticText 2'); $booking_dlg->{Ctl_Booking_Referring_Doctor_Ref_4_Txt} = i_staticT +ext->new($booking_dlg->{booking_main}, wxID_ANY, "", wxDefaultPositio +n, __xy_size(100), ); $mu->record('after i_Booking i_staticText 2'); $booking_dlg->{Ctl_Booking_Referring_Doctor_Ref_4_Txt}->SetFont($l +oc_font_wx);

      The output is unchanged:

      0 773984 ( 0) 193264 ( 0) 43436 ( 0) 8 ( +0) 368884 ( 0) after i_Booking set focus 0 773984 ( 0) 193264 ( 0) 43436 ( 0) 8 ( +0) 368884 ( 0) before i_Booking i_staticText 1 0 773984 ( 0) 193264 ( 0) 43436 ( 0) 8 ( +0) 368884 ( 0) after i_Booking i_staticText 1 0 774604 ( 620) 193264 ( 0) 43436 ( 0) 8 ( +0) 368884 ( 0) before i_Booking Ctl_Booking_Referring_Doctor_Ref +_4_Lbl

      But even so, the variable should be destroyed when it moves out of scope and it is not, so I suspect some sort of circular reference. I just can't see it.

      Steve.

        But even so, the variable should be destroyed when it moves out of scope and it is not, so I suspect some sort of circular reference. I just can't see it.

        If $booking_dlg->{booking_main} contains a reference to $booking_dlg? Then this is a circular reference:

        $booking_dlg->{Ctl_Booking_Referring_Doctor_Txt} = i_staticText->new($ +booking_dlg->{booking_main}

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
        In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked
Re: Detecting memory leaks.
by RichardK (Parson) on May 04, 2015 at 15:53 UTC

    Is there any difference between Wx::StaticText->new(...) and i_staticText->new(...) ?

      Hi Richard,

      Yes, Wx::StaticText->new(...) is the standard call, but on Linux you cannot set the background attributes.

      i_staticText->new(...) is based on Wx::Panel, to give it a background and then Wx::StaticText->new(...) is within the panel. That way I can adjust the background attributes like background colour and length of field.

      Regards

      Steve

Re: Detecting memory leaks.
by Anonymous Monk on May 04, 2015 at 17:49 UTC

    What convinced you the problem has to be a memory leak, as opposed to memory corruption? Could you try valgrind with --free-fill and --malloc-fill?

    Did you run it under gdb to see where and how it faults? A SEGV could be something as simple as exceeding stack ulimit.

      Well, thanks for asking that question. It made me think. I guessed it might be a leak because the memory being utilised seemed to be increasing the longer I ran it, but in an unpredictable way.

      However, Valgrind gives the following, but it doesn't particularly seem to depend on any segment of code:

      ==2576== LEAK SUMMARY: ==2576== definitely lost: 731,689 bytes in 54,909 blocks ==2576== indirectly lost: 68,896 bytes in 2,326 blocks ==2576== possibly lost: 37,769,458 bytes in 52,844 blocks ==2576== still reachable: 78,109,700 bytes in 547,738 blocks ==2576== suppressed: 0 bytes in 0 blocks ==2576== Reachable blocks (those to which a pointer was found) are not + shown. ==2576== To see them, rerun with: --leak-check=full --show-leak-kinds= +all ==2576== ==2576== For counts of detected and suppressed errors, rerun with: -v ==2576== ERROR SUMMARY: 2610 errors from 2610 contexts (suppressed: 1 +from 1) image@iExam_SD_0003:~/Documents/Endoscopia$

      as it gives a similar dump to this even when I do ctrl-c immediately on start-up.

      Regards

      Steve

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1125580]
Approved by BrowserUk
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (5)
As of 2024-04-19 04:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found