7th Kevin has asked for the wisdom of the Perl Monks concerning the following question:

I had the following code in an XS module. It is attempting to cycle through all of the entries in the scratchpad associated with a sub, and for each entry having a valid name, where the name also is found in another hash, I want to do something.

for (i = 0; i <= av_len(padn); ++i) { HE *hent; SV **nameptr = av_fetch(padn, i, 0); if (nameptr != NULL && SvPOKp(*nameptr) && (hent = hv_fetch_ent(hvn, *nameptr, 0, 0)) != NULL) { /* do something interesting with the value from hent */ } }

This worked, most of the time. However, for two of the names I was interested in, *nameptr was valid but the hv_fetch_ent failed, even though the name was in the hash indicated by hvn (which is HV *).

I then changed it to something like this:

for (i = 0; i <= av_len(padn); ++i) { HE *hent; SV **nameptr = av_fetch(padn, i, 0); if (nameptr != NULL && SvPOKp(*nameptr)) { SV **field; U32 len; const char *name = SvPV(*nameptr, len); if ((field = hv_fetch(hvn, name, len, 0)) != NULL) { /* do something interesting with *field */ } } }

but that failed in the same way.

I did some research (i.e., lots of printfs) and discovered that in these two cases _only_, the length associated with *nameptr was too large. One of the values was six characters long, the other was 5 (names "@stack" and "@trim" respectively), but the lengths were 235 and 236, respectively. I found it interesting but not enlightening that the wrong values were both 241 minus the correct value.

The code I have now works, but I am less than happy with it:

for (i = 0; i <= av_len(padn); ++i) { SV **nameptr = av_fetch(padn, i, 0); if (nameptr != NULL && SvPOKp(*nameptr)) { SV **field; const char *name = SvPV_nolen(*nameptr); if ((field = hv_fetch(hvn, name, strlen(name), 0)) != NULL) { /* do something interesting with *field */ } } }

In other words, the length associated with the SV* is wrong, but using good ol' C "strlen" works. Huh?

I know this borders on (if it doesn't cross into) forbidden magic, so maybe I should just accept that there are things I wasn't Meant To Know, but I am interested to hear if anyone has any clues about this Why didn't the length match up? Why did only some of them not match up (I didn't mention it, but one of the things I did was print out the name and name lengths of everything where *nameptr was valid). Why did the same names work properly some places?

This is perl, v5.8.6 built for darwin-thread-multi-2level (with 3 registered patches, see perl -V for more detail)

Kevin, perplexed

Replies are listed 'Best First'.
Re: Invalid SV name length in pad?
by dave_the_m (Monsignor) on Jul 06, 2007 at 10:03 UTC
    Under some circumnstances, perl uses the SvCUR length field of pad names to store other information. So you have to use strlen.

    know this borders on (if it doesn't cross into) forbidden magic.

    You are actually heavily into forbidden magic here. In perl 5.9.x, the way pads are maniplated has changed quite significantly, and your code most likely will no longer work.

    Dave.

      OK, so I'm not going crazy. (Yet.) *Whew!*

      (And I'm aware this is likely to fail at any time...not planning on doing anything production-wise with it, just experimenting.)

      Thank you very much for demystifying me!

Re: Invalid SV name length in pad?
by diotalevi (Canon) on Jul 06, 2007 at 02:05 UTC

    Did you perhaps have multi-byte unicode characters in your names?

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊