This is something you are probably NOT supposed to be doing with #perl but consider my innocent looking C code found in an Inline::C region (which will be discussed in my talk).
If my understanding of the API is correct, then this macro allocates a buffer of known size in bytes and puts the buffer under the #Perl garbage collector. One only needs an entry point from Perl to #C and one just enhanced their #Clang code with a garbage collector
for safe memory management.
@Perl
@Perl We use C to make things run faster in #perl but why not think of turning the tables? Having Perl make C somewhat safer to use, leave IO and string pains behind (jump from #C back to Perl)
1. screenshot has alt-text
2. yes, I am aware that the arguments of the macro should probably be inside parentheses
@Perl There is another more sinister pattern that one can apply to do safe memory management in *assembly* that I will blog about at some point. None of these patterns prevent things like out of bounds access - they are merely there to prevent memory management FAFO
@ChristosArgyrop @Perl I don't see any garbage collecting. If you don't register sv
for cleanup later, it'll probably just leak.
(Also, why not just SV *sv = newSVpvn(buf, buffer_size);
?)
Regarding the allocation sequence (comments all based on my understanding of perlguts)
1) newSVpvn(const char*, STRLEN) -> allocates STRLEN+1 (for C's 'terminal \0') while
2) Newxz gives one the size they want (
3) sv_usepvn_flags can then be applied and the buffer now belongs to perl (see screenshot) through the SV that was just created to hold it
@ChristosArgyrop @Perl SV_HAS_TRAILING_NUL
promises that buf[buffer_size] == '\0'
(i.e. buf
has actually buffer_size+1
elements). In your code, that's not the case, so that's not a valid PV string buffer. See https://perldoc.perl.org/perlapi#sv_usepvn_flags:
And if
flags & SV_HAS_TRAILING_NUL
is true, thenptr[len]
must beNUL
, and the realloc will be skipped (i.e., the buffer is actually at least 1 byte longer thanlen
, and already meets the requirements for storing inSvPVX
).
(Also, SV_MAGIC
seems weird for a newly allocated SV, which is guaranteed to not have magic.)
@barubary @Perl
Hm, I am not using these SV as strings, I am allocating a space of sufficient size to hold a C struct, and lie to perl that it has a terminal zero to avoid copying the buffer to a new area in memory and have its size extended by 1 to hold the terminal '\0'
It is easy to see that memory does not leak by creating an example in which the SV is mortalized. Code in alt text. Upon execution there is a warning about the freeing of the area allocated in C when the program terminates.
@ChristosArgyrop @Perl That's not how the API is intended to work. And on a debugging Perl, that will just crash due to an assertion failure: https://github.com/Perl/perl5/blob/ee4e4f68dd9b1c3924f0750b92245e6855f12778/sv.c#L5250-L5253
@barubary @Perl
Agreed that the SV_MAGIC is weird, but look at the examples
https://perldoc.perl.org/perlguts#Working-with-SVs
Every single one of the sets the MAGIC flag when working in C with buffers.
There is probably some undocumented MAGIC that requires the MAGIC to be set.