Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re: What difference between malloc and Newx, how attach a C string to SV directly?

by xiaoyafeng (Deacon)
on Sep 30, 2019 at 02:46 UTC ( [id://11106853]=note: print w/replies, xml ) Need Help??


in reply to What difference between malloc and Newx, how attach a C string to SV directly?

Thanks Everyone for your help! After doing some dig with your valuable suggestion, I attach a C string (string constant) to a SV successfully. Here is the UPDATE

When attach an mem-chunk to an SV, perl does much work for you background, not just save a pointer address. First, perl free the previous PV in SV, then perl will realloc this mem size to mem size +2bytes( I don't understand why though), last, perl set cur and len slot and return. So if you want to attach a C string, you must tell perl not doing so many smarts:

use strict; use warnings; use Devel::Peek; my $x = ""; Dump $x; ddd($x); print $x; Dump $x; use Inline Config => BUILD_NOISY => 1, ClEAN_AFTER_BUILD =>0; use Inline 'C' => 'Config' => ccflagsex => "-g"; use Inline 'C' => <<'CODE'; int ddd(SV* x){ char* dx = "dddddd\n"; printf("string dx is %p \n", dx); // You have to use sv_use* family, since these functions free the prev +ious PV in SV first for you, but don't use sv_usepvn otherwise perl w +ill realloc pv. sv_usepvn_flags(x, dx, 8, SV_HAS_TRAILING_NUL); // Thanks ikegami, must set LEN to 0, otherwise, perl will try to free + SV when leave scope. SvLEN_set(x, 0); return 0; } CODE
As a interesting side-effect, I found you can't enlarge the SV containing C string by using .=, no any error throw though.

__END__ SV = PV(0x55ac3017e050) at 0x55ac301a20b8 REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) PV = 0x55ac30220b00 ""\0 CUR = 0 LEN = 10 COW_REFCNT = 1 string dx is 0x7f0adfd33bfd dddddd SV = PV(0x55ac3017e050) at 0x55ac301a20b8 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x7f0adfd33bfd "dddddd\n\0" CUR = 8 LEN = 0




I am trying to improve my English skills, if you see a mistake please feel free to reply or /msg me a correction

Replies are listed 'Best First'.
Re^2: What difference between malloc and Newx, how attach a C string to SV directly?
by ikegami (Patriarch) on Sep 30, 2019 at 08:33 UTC

    Bug 1:

    You are including the NUL in the buffer, and you are falsely claiming there is a trailing NUL after the buffer.

    sv_usepvn_flags(x, dx, 8, SV_HAS_TRAILING_NUL);
    should be
    sv_usepvn_flags(x, dx, 7, SV_HAS_TRAILING_NUL);
    and it should be written as
    sv_usepvn_flags(x, dx, strlen(dx), SV_HAS_TRAILING_NUL);

    Bug 2:

    The buffer can't be modified, but you offer no protection. For example, $x =~ s/./a/s; will result in undefined behaviour (which fortunately segfaults on my machine).

    Add the following:

    SvREADONLY_on(x);

    I found you can't enlarge the SV containing C string by using .=, no any error throw though.

    I already mentioned that. Or rather, I mentioned that it causes the buffer to get replaced with a new one that contains a copy.

    Before $x .= "a";:

    SV = PV(0x3e1a1785e0) at 0x3e1a197528 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x35260c8bbd5 "dddddd" <-- Pointer into C static storage CUR = 6 LEN = 0 <-- Doesn't belong to Perl.

    After $x .= "a";:

    SV = PV(0x3e1a1785e0) at 0x3e1a197528 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x3e1a19fe50 "dddddda"\0 <-- New buffer (copy + "a") CUR = 7 LEN = 17 <-- Belongs to Perl.

    However, SvREADONLY_on(x) will prevent this. So if you want to allow this, you'll need to remove the READONLY flag, which means you'll need to make a copy of the constant string.

      Many Thanks, ikegami, just one question, how perl decide to realloc pv or just make a copy?

        If the scalar's SvLEN is 0, the buffer exists outside of Perl's memory allocation system, so Perl must allocate a new buffer if it needs a larger buffer.

        If the scalar's copy-on-write count is larger than 1, that means two scalars are sharing the buffer, so Perl must allocate a new buffer if it needs to change the contents or size of the buffer.

        Unless I'm missing something, Perl should otherwise realloc if it needs more space, which will extend the existing buffer if possible.

        Note that Perl typically over-allocates to accommodate future growth.

        There are a couple of optimizations (copy-on-write, mortal buffer stealing) that will replace a scalar's buffer when you assign to it. But that's specifically done to avoid copying, so that's different.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11106853]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (None)
    As of 2024-04-25 01:53 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      No recent polls found