(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.