Devel::...:Object(3)

πŸ“¦
version 0.08 Β· 2 versions
, in fedora 43

πŸ’– Devel::LeakGuard::Object πŸ’–

okay bestie, so this is the Devel::LeakGuard::Object(3) page β€” it lives in the User Contributed Perl Documentation section and it's literally about catching your objects when they refuse to die. leak detection, but make it scoped. 🫢

✨ NAME ✨

Devel::LeakGuard::Object β€” Scoped checks for object leaks

🌸 VERSION 🌸

This document describes Devel::LeakGuard::Object version 0.08

πŸ¦‹ SYNOPSIS πŸ¦‹

# Track a single object
use Devel::LeakGuard::Object;
my $obj = Foo::Bar->new;
Devel::LeakGuard::Object::track($obj);

# Track every object
use Devel::LeakGuard::Object qw( GLOBAL_bless );

# Track every object, summary at exit
use Devel::LeakGuard::Object qw( GLOBAL_bless :at_end );

# Track a block of code, warning on leaks
leakguard {
    # your potentially leaky code here
};

# Track a block of code, die on leaks
leakguard {
    # your potentially leaky code here
}
on_leak => 'die';

πŸ‘‘ DESCRIPTION πŸ‘‘

so basically this module tracks objects for you, and the whole point is catching memory leaks β€” the ones that sneak in via circular references or, like, inappropriate caching schemes πŸ™ˆ (yes that's a real phrase and yes it's shady behaviour).

It's derived from, and backwards compatible with, Adam Kennedy's Devel::Leak::Object. Any errors are mine. (their words, and honestly iconic of them to say it πŸ’…)

Here's the tea on how it works: it overrides bless and slaps a synthetic DESTROY method onto any tracked classes, so it can keep a count of blessed objects per-class. lowkey genius.

Object tracking can be enabled:

  • for an individual object
  • for a block of code
  • globally

πŸŽ€ Tracking an individual object

Track individual objects like this:

use Devel::LeakGuard::Object qw( track );

# Later...
track( my $obj = new Foo );

πŸŽ€ Tracking object leaks in a block of code

To detect any object leaks in a block of code:

use Devel::LeakGuard::Object qw( leakguard );

leakguard {
    # your code here.
};

πŸŽ€ Tracking global object leaks

use Devel::LeakGuard::Object qw( GLOBAL_bless );

πŸŽ€ Finding out what leaked

If you use leakguard (recommended, bestie, do this one) then by default a warning is thrown when leaks are detected. You can customise this behaviour by passing options to leakguard; see the documentation for leakguard for more information.

If you use GLOBAL_bless or track then you can also specify the :at_end option

use Devel::LeakGuard::Object qw( GLOBAL_bless :at_end );

in which case a summary of leaks will be displayed at program exit. πŸ’€

πŸŽ€ Load early!

Devel::LeakGuard::Object can only track allocations of objects compiled after it is loaded β€” so load it as early as possible. fr fr. early bird gets the leak report. 🐦

πŸŽ€ What is a leak?

This module counts the number of blessed instances of each tracked class. When we talk about a 'leak' what we really mean here is an imbalance in the number of allocated objects across some boundary. Using this definition we see a leak even in the case of expected imbalances.

When interpreting the results you need to remember that it may be quite legitimate for certain allocations to live beyond the scope of the code under test.

You can use the various options that leakguard supports to filter out such legitimate allocations that live beyond the life of the block being checked.

πŸŽ€ Performance

As soon as Devel::LeakGuard::Object is loaded bless is overloaded. That means that bless gets a little slower everywhere. When not actually tracking the overloaded bless is quite fast β€” but still around four times slower than the built-in bless.

Bear in mind that bless is fast and unless your program is doing a huge amount of blessing you're unlikely to notice a difference. On my machine core bless takes around 0.5 μS and loading Devel::LeakGuard::Object slows that down to around 2 μS. not too bad, honestly. 🌈


πŸ’… INTERFACE πŸ’…

🧚 leakguard

Run a block of code tracking object creation and destruction and report any leaks at block exit.

At its simplest leakguard runs a block of code and warns if leaks are found:

leakguard {
    my $foo = Foo->new;
    $foo->{me} = $foo; # leak
};

# Displays this warning:
Object leaks found:
  Class Before  After  Delta
  Foo        3      4      1
Detected at foo.pl line 23

If you really don't want to leak you can die instead of warning:

leakguard {
    my $foo = Foo->new;
    $foo->{me} = $foo; # leak
}
on_leak => 'die';

If you need to do something more complex you can pass a coderef to the on_leak option:

leakguard {
    my $foo = Foo->new;
    $foo->{me} = $foo; # leak
    my $bar = Bar->new;
    $bar->{me} = $bar; # leak again
}
on_leak => sub {
    my $report = shift;
    for my $pkg ( sort keys %$report ) {
      printf "%s %d %d\n", $pkg, @{ $report->{$pkg} };
    }
    # do something
};

In the event of a leak the sub will be called with a reference to a hash. The keys of the hash are the names of classes that have leaked; the values are refs to two-element arrays containing the bless count for that class before and after the block so the example above would print:

Foo 0 1
Bar 0 1

πŸ“ Options

Other options are supported. Here's the full list:

  • on_leak β€” What to do if a leak is detected. May be 'warn' (the default), 'die', 'ignore' or a code reference. If on_leak is set to 'ignore' no leak tracking will be performed.
  • only β€” If you need to concentrate on a subset of classes use only to limit leak tracking to a subset of classes:
leakguard {
    # do stuff
}
only => 'My::Stuff::*';

The pattern to match can be a string (with '*' as a shell-style wildcard), a Regexp, a coderef or a reference to an array of any of the above. This (improbable) example illustrates all of these:

leakguard {
    # do stuff
}
only => [
    'My::Stuff::*',
    qr{Leaky},
    sub { length $_ > 20 }
];

That would track classes beginning with 'My::Stuff::', containing 'Leaky' or whose length is greater than 20 characters.

  • exclude β€” To track all classes apart from a few exceptions use exclude. The exclude spec is like an only spec but classes that match will be excluded from tracking.
  • expect β€” Sometimes a certain amount of 'leakage' is acceptable. Imagine, for example, an application that maintains a single cached database connection in a class called My::DB. The connection is created on demand and deleted after it has been used 100 times β€” to be created again next time it's needed.

We could use exclude to ignore this class β€” but then we'd miss the case where something goes wrong and we create 5 connections at a time.

Using exclude we can specify that no more than one My::DB should be created or destroyed:

leakguard {
    # do stuff
}
expect => {
    'My::DB' => [ -1, 1 ]
};

🧚 leakstate

Get the current allocation counts for all tracked objects. If GLOBAL_bless is in force this will include all blessed objects. If you are using the finer-grained tracking tools (track and leakguard) then only allocations that they cover will be included.

Returns a reference to a hash with package names as keys and allocation counts as values. cute little hash, very informative. πŸ’œ

🧚 track

Track an individual object. Tracking an object increases the allocation count for its package by one. When the object is destroyed the allocation count is decreased by one. Current allocation counts may be retrieved using leakstate.

If the object is reblessed into a different package the count for the new package will be incremented and the count for the old package decremented. ✨ glow-up for that object, honestly.

🧚 status

Print out a Devel::Leak::Object style summary of current object allocations. If you

use Devel::LeakGuard::Object qw( GLOBAL_bless :at_end );

then status will be called at program exit to dump a summary of outstanding allocations.


🌟 DEPENDENCIES 🌟

List::Util, Scalar::Util, Test::Differences, Test::More

πŸ”₯ SEE ALSO πŸ”₯

Devel::Leak::Object

πŸ™ˆ INCOMPATIBILITIES πŸ™ˆ

None reported.

πŸ’€ BUGS AND LIMITATIONS πŸ’€

Please report any bugs or feature requests via https://github.com/AndyA/Devel--LeakGuard--Object/issues.

⭐ AUTHOR ⭐

Andy Armstrong "<andy@hexten.net>"

Based on code taken from Adam Kennedy's Devel::Leak::Object which carries this copyright notice:

Copyright 2007 Adam Kennedy.

Rewritten from original copyright 2004 Ivor Williams.

Some documentation also copyright 2004 Ivor Williams.

Copyright (c) 2009-2015, Andy Armstrong "<andy@hexten.net>".

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.


and that's the whole page bestie, mwah πŸ’‹ this was perl v5.42.0, dated 2025-07-25 β€” go forth and catch those leaks, you absolute icon πŸ‘‘πŸ«Ά

πŸ“¦ where this page comes from