develooper Front page | perl.perl5.porters | Postings from July 2003

Storing &PL_sv_undef as a hash key with perl-5.8.x

Thread Next
Marcus Holland-Moritz
July 18, 2003 03:34
Storing &PL_sv_undef as a hash key with perl-5.8.x
Message ID:
I've just been debugging Devel::Size today and found that what seems
to be intuitively correct code does not work with perls >= 5.8.0 due
to the way restricted hashes are implemented.

Devel::Size has the following snippet...

  hv_store(tracking_hash, (char *)&thing, sizeof(void *), &PL_sv_undef, 0);

...and checks for that key later using...

  if (hv_exists(tracking_hash, (char *)&thing, sizeof(void *)))

...which seems perfectly legal, except that it doesn't work.

Since 5.8.0, having hash values set to &PL_sv_undef causes the hash
entries to be treated as 'placeholders'. Thus, they do not appear when
checking with hv_exists() or iterating over the hash.

Even worse, this behaviour is _only_ documented in the description for
hv_iternext_flags (at least, I didn't find it documented anywhere
else). Someone who knows XS from before 5.8.0 or someone who is new
to XS will hardly find this information. Besides, it's absolutely
counterintuitive to use &PL_sv_undef for just about everything, but
not being allowed to use it as hash values. And it can take you ages
to find out what's going wrong if you've run into that problem.
As perlguts (5.8.1) says:

  The scalar undef value is stored in an SV instance called PL_sv_undef.
  Its address can be used whenever an SV* is needed.

So IMHO this is either a bug, because it breaks existing, intuitively
correct code (at least it broke Devel::Size and my own Convert::Binary::C)
or the behaviour is far too badly documented (in which case it's a
documentation bug).
Besides, I don't like the idea of allocating a new empty SV every time
I need an undefined value (in a hash). This only eats up memory that is
never going to be used. I guess that was the reason for having only a
single global PL_sv_undef.

If this is not going to be changed, the behaviour has to be documented
at least within the descriptions of hv_store() and hv_store_ent() in
perlapi. There also has to be a description on how to work around this
limitation properly.

-- Marcus

Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About