(note: I've copied this over from my use.perl.org journal, because it was so useful I didn't want anyone to miss it. I've omitted code because I solved this in an internal application; if anyone's interested in a complete example, let me know in the comments. The basic method should be clear.)

(note 2: fixed a typo and a tago.)

I was working on some code today, creating tests, and one of my tests started printing this message at termination:

Use of uninitialized value in subroutine entry at /home/y/lib/perl5/si +te_perl/5.8/Log/Log4perl.pm line 132 during global destruction.
I'd used Log::Log4perl to track the destruction of some of my objects (they're tied to SWIG structures, and can easily build up a lot of wasted memory if they're not destroyed appropriately). This was an odd message; it seemed to be telling me I hadn't set up Log4perl properly. I added
use Log::Log4perl qw(:easy); Log::Log4perl->easy_init($ERROR);
because I wasn't interested in seeing the debug messages at this point. Same error. Hm. Time to read some documentation.

Checking the Log4perl FAQ told me that this means I have a circular reference somewhere in my code. Trying the easy and obvious thing first, I used Devel::Cycle and tried running it on the object that was being destroyed ... except that wasn't the object with the leak. D'oh. So how was I going to locate the leaky object? I tried using Devel::Leak at the beginning and end of my code, but I got a huge SV dump that looked like I would have to print out and then connect things together with arrows by hand. I had confirmed that I definitely had a leak, but this looked like, you know, work to figure out.

I'm far too lazy to do that, so I thought about it a while instead. I had a small test case that duplicated the problem. How could I zero in on the point where I created the circular reference?

The light came on: the debugger! I knew that I could detect when the circular reference had been created, because Log4perl would throw its error during global destruction. So all I had to do was run through the code in the debugger, continuing to each point where I created more objects ... and then simply do a q to exit the program at that point! When I got to a line that threw the error, I knew that piece of code had created the circular reference.

In just a few minutes, I was able to zero in on the method that was creating the circular reference, and in just a minute more, to find exactly the piece of code that had created the problem. Toss in a weaken(), problem solved.


In reply to Easily finding circular references by pemungkah

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.