in reply to Re^5: SvUV vs SvIV for pointers in SVs, typemap
in thread SvUV vs SvIV for pointers in SVs, typemap

The SV is not intended to be modifiable. It's just a container for an opaque value. The only "manipulation" being done is to cast the value back to a pointer.

Have you tried running Perl on a 32-bit system configured for /3GB?

No. Are you saying that sv = (SV*)(IV)sv fails then? If so, that's a bug. IV is guaranteed to be large enough to hold a pointer.

Replies are listed 'Best First'.
Re^7: SvUV vs SvIV for pointers in SVs, typemap
by BrowserUk (Patriarch) on Feb 21, 2011 at 01:47 UTC

    You are still assuming that you (or "the programmer") would be in control of all the code that might operate upon pointer values stored within an SV.

    Ask yourself how and why a pointer value might end up in the IV slot of an SV.

      I'm making no such assumption. I'm saying nothing should be operating on the SV. If something does play with the internals of this object, it's their own fault if they mess something up.

      Ask yourself how and why a pointer value might end up in the IV slot of an SV.

      The XS library is creating a handle that will later be passed back to it.

      In Windows, is HANDLE signed or unsigned? The answer is that it doesn't matter.

      Update: Example use of that typemap:

      $ cat a.pl use strict; use warnings; use Inline C => <<'__EOI__', PREFIX => 'M_'; #include <stdio.h> typedef struct { int i; int j; } foo_t; foo_t* M_get() { foo_t* foo = (foo_t*)malloc(sizeof(foo_t)); printf("get: %p\n", foo); return foo; } void M_free(foo_t* foo) { printf("free(%p)\n", foo); free(foo); } __EOI__ my $o = get(); free($o); $ cat typemap TYPEMAP foo_t* T_PTRREF $ perl -MInline=FORCE,NOISY,NOCLEAN a.pl ... get: 0x91ab70 free(0x91ab70)
      #!/usr/bin/perl -w use Devel::Peek; $ptrUV = unpack('J',pack('P[12]',"Hello World")); $ptrIV = unpack('j',pack('P[12]',"Hello World")); print Dump($ptrUV); print Dump($ptrIV); $ptrUV += 2**31; print Dump($ptrUV);


      SV = IV(0x182a260) at 0x182a264 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 28545556 SV = IV(0x182a3e0) at 0x182a3e4 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 26107564 SV = IV(0x182a260) at 0x182a264 REFCNT = 1 FLAGS = (IOK,pIOK,IsUV) UV = 2176029204
      Perl keeps all unsigneds as IVs until they are greater than IV_MAX (~ +2 billion), then it uses the UV flag/UV mode. [sv.c#l1620 in perl.git] But, if the pointer is larger than 2 billion, and the user manipulates the pointer, for struct offsets for example, before passing it to unpack, or passes the scalar with the pointer inside it to an XSUB that takes a pointer (bad XSUB design right?)

        If someone changes your internals to the point of failure, it doesn't make your design bad.

        Besides, if you were to fake the internals using pack and ended up with a UV, it would still work with the existing typemap.

        There is also the possibility of performing pointer arithmetic with two pointers, one just before the 2GB boundary and one just after it. Thus mixing IV and UV math.

        Whether deriving offsets in structs, or extracting or manipulating sub-strings, I'm not at all convinced that there are not places within the Perl sources themselves where such manipulations are done, that work only because most 32-bit Perls run limited to 2GB.

        Certainly, when I was playing with 32-bit perl made /largeaddressaware and with /3GB set, I saw enough weirdness and crashes to give up on the idea of using that instead of a 64-bit Perl in order to get access to my full complement of ram.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.