5

I want to use Perl hash in my C code (XS) as a set, so I only need to keep keys in hash. Is it possible to store something like null or another constant value to avoid creating unnecessary value?

Something like this:

int add_value(HV *hash, SV *value)
{
    // just an example of key
    char key[64];
    sprintf(key, "%p", value);
    if (hv_exists(hash, key, strlen(key)) return 0;

    // here I need something instead of ?
    return hv_stores(hash, key, ?) != NULL;
}

One of possible solution could be to store value itself, but maybe there is special constant for undef or null.

John Tracid
  • 3,836
  • 3
  • 22
  • 33

2 Answers2

5

&PL_sv_undef is the undefined value, but you can't, unfortunately, use it naively in hashes and arrays. Quoting perlguts:

Generally, if you want to store an undefined value in an AV or HV, you should not use &PL_sv_undef , but rather create a new undefined value using the newSV function, for example:

av_store( av, 42, newSV(0) );
hv_store( hv, "foo", 3, newSV(0), 0 );
pilcrow
  • 56,591
  • 13
  • 94
  • 135
4

&PL_sv_undef is the undef scalar. It's read-only. You probably want a fresh undef scalar, as created using newSV(0)[1].

The scalar returned by newSV(0) starts with a refcount of one, of which the hash "takes possession" when the scalar is stored in it using hv_stores, so don't SvREFCNT_dec or sv_2mortal the returned scalar. (Do increase the reference count if you store it elsewhere too.)


  1. # "The" undef (A specific read-only variable that will never get deallocated)
    $ perl -MDevel::Peek -e'Dump(undef)'
    SV = NULL(0x0) at 0x3596700
      REFCNT = 2147483641
      FLAGS = (READONLY,PROTECT)
    
    # "An" undef (It's not the type of SVt_NULL that make it undef...)
    $ perl -MDevel::Peek -e'Dump($x)'
    SV = NULL(0x0) at 0x1bb7880
      REFCNT = 1
      FLAGS = ()
    
    # Another undef (... It's the lack of "OK" flags that make it undef)
    $ perl -MDevel::Peek -e'$x="abc"; $x=undef; Dump($x)'
    SV = PV(0x3d5f360) at 0x3d86590
      REFCNT = 1
      FLAGS = ()
      PV = 0
    
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • So I have to release it manually before releasing hash with `hv_undef()`? – John Tracid Aug 05 '15 at 15:48
  • No, as part of clearing a hash, the refcount of the scalars therein will get decremented. – ikegami Aug 05 '15 at 15:51
  • You should never have to use `undef(%hash)` aka `hv_undef(hv)`. You probably want `%hash=()` aka `hv_clear(hv)` on the rare occasion that you want to empty the hash. – ikegami Aug 05 '15 at 15:52
  • yes; either you intend to use the hash again, in which case hv_undef will clear some things (I believe) that then will just have to be reallocated, or you don't, in which case you should be freeing the hash, not undefing it. – ysth Aug 05 '15 at 16:20