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

Re^7: Perl XS binding to a struct with an array of chars*

by Marshall (Canon)
on Nov 24, 2022 at 22:24 UTC ( [id://11148362]=note: print w/replies, xml ) Need Help??


in reply to Re^6: Perl XS binding to a struct with an array of chars*
in thread Perl XS binding to a struct with an array of chars*

I have Inline::C working on my system now. Before proceeding further, I decided to make a little test to see what malloc() is doing. Often more memory is allocated than requested and I wanted to see if I could get an idea of "how much more?". Sometimes there is a lucky accident where the code works although it is not guaranteed to work.

I have 2 programs.
1) 32 bit gcc independent of Perl
2) 64 bit gcc that is part of my 64 bit Perl 5.24 installation

Code for both is shown below.
For 32 bit version, I am not surprised to see 64 bit instead of 32 bit alignment (lower 3 address bits always zero). 64 bit alignment also appears to be the case for the 64 bit gcc code as well. Anyway the alignment drives the absolute minimum memory allocation unit. In both cases, 8 bytes (64 bit alignment). The question is then whether there is additional space due to the quanta that malloc() uses to track allocation?

The 32 bit standalone version does the exact same thing every run. I don't know why there is the difference between 2nd and 1st allocation, but after that we see the pattern of 16 bytes given for a single byte requested.

The 64 bit inline C does something different every run! For all I know this could be some kind of Perl security feature?

Anyway, I thought the results relevant to our discussion about allocation of this weird type.

#include <stdio.h> #include <stdlib.h> //testing malloc() this is 32 bit gcc - separate from Perl void testMalloc(void) { char* x = (char *) malloc(1); printf (" Byte Starting Memory Addr is %p\n",x); char* y = (char *) malloc(1); printf ("Next Byte Starting Memory Addr is %p\n",y); printf ("difference in bytes between byte2 and byte1 = %d\n",y-x); char* z = (char *) malloc(1); printf ("Next Byte Starting Memory Addr is %p\n",z); printf ("difference in bytes between byte3 and byte2 = %d\n",z-y); char* alpha = (char *) malloc(1); printf ("Next Byte Starting Memory Addr is %p\n",alpha); printf ("difference in bytes between byte4 and byte3 = %d\n",z-y); free(x); free(y); free(z); free(alpha); return; } int main(int argc, char *argv[]) { testMalloc(); exit(0); } /* Byte Starting Memory Addr is 00C92FD8 Next Byte Starting Memory Addr is 00C90CC8 difference in bytes between byte2 and byte1 = -8976 Next Byte Starting Memory Addr is 00C90CD8 difference in bytes between byte3 and byte2 = 16 Next Byte Starting Memory Addr is 00C90CE8 difference in bytes between byte4 and byte3 = 16 */ /* Byte Starting Memory Addr is 00B22FD8 Next Byte Starting Memory Addr is 00B20CC8 difference in bytes between byte2 and byte1 = -8976 Next Byte Starting Memory Addr is 00B20CD8 difference in bytes between byte3 and byte2 = 16 Next Byte Starting Memory Addr is 00B20CE8 difference in bytes between byte4 and byte3 = 16 */
################################################# # testing malloc 64 bit Perl use strict; use warnings; use Inline C => Config => BUILD_NOISY => 1, CLEAN_AFTER_BUILD => 0, USING => 'ParseRegExp', ; use Inline "C"; testMalloc(); =OUTPUT: Byte Starting Memory Addr is 000000000308CE68 Next Byte Starting Memory Addr is 000000000308D258 difference in bytes between byte2 and byte1 = 1008 Next Byte Starting Memory Addr is 000000000308D018 difference in bytes between byte3 and byte2 = -576 Next Byte Starting Memory Addr is 000000000308D0A8 difference in bytes between byte4 and byte3 = -576 =cut =AnotherRun: Byte Starting Memory Addr is 00000000031157D8 Next Byte Starting Memory Addr is 0000000003115B98 difference in bytes between byte2 and byte1 = 960 Next Byte Starting Memory Addr is 0000000003115E98 difference in bytes between byte3 and byte2 = 768 Next Byte Starting Memory Addr is 0000000003115F88 difference in bytes between byte4 and byte3 = 768 =cut =yet Another Run Byte Starting Memory Addr is 0000000002EA6CF8 Next Byte Starting Memory Addr is 0000000002EA6EA8 difference in bytes between byte2 and byte1 = 432 Next Byte Starting Memory Addr is 0000000002EA7AA8 difference in bytes between byte3 and byte2 = 3072 Next Byte Starting Memory Addr is 0000000002EA7C58 difference in bytes between byte4 and byte3 = 3072 =cut =one more time Byte Starting Memory Addr is 000000000313CE38 Next Byte Starting Memory Addr is 000000000313C5F8 difference in bytes between byte2 and byte1 = -2112 Next Byte Starting Memory Addr is 000000000313C868 difference in bytes between byte3 and byte2 = 624 Next Byte Starting Memory Addr is 000000000313CA48 difference in bytes between byte4 and byte3 = 624 =cut __END__ __C__ void testMalloc(void) { char* x = (char *) malloc(1); printf (" Byte Starting Memory Addr is %p\n",x); char* y = (char *) malloc(1); printf ("Next Byte Starting Memory Addr is %p\n",y); printf ("difference in bytes between byte2 and byte1 = %d\n",y-x); char* z = (char *) malloc(1); printf ("Next Byte Starting Memory Addr is %p\n",z); printf ("difference in bytes between byte3 and byte2 = %d\n",z-y); char* alpha = (char *) malloc(1); printf ("Next Byte Starting Memory Addr is %p\n",alpha); printf ("difference in bytes between byte4 and byte3 = %d\n",z-y); free(x); free(y); free(z); free(alpha); return; }

Replies are listed 'Best First'.
Re^8: Perl XS binding to a struct with an array of chars*
by syphilis (Archbishop) on Nov 25, 2022 at 00:31 UTC
    I decided to make a little test to see what malloc() is doing

    I pretty much always use "Newx" or "Newxz" instead of "malloc" because I read somewhere that they are the recommended XS way of allocating memory.
    However, I've always found the 2 alternatives to be interchangeable.
    Maybe there are some systems and/or perl configurations where they cannot be used interchangeably but, to my knowledge, I've not encountered such a case.
    IME, doing Newx(x, 42, datatype) is effectively the same as doing x=malloc(42 * sizeof(datatype)).
    The important difference is that the former allocation must be released by "Safefree", whereas the latter must be released by "free".

    Therein lies the sum of my knowledge of memory allocation ;-)

    Cheers,
    Rob

      Probably you already know this, but the z variant zeros the allocated memory (Re^3: help with XS (Newx and) so you pay a little time for possibly a little more safety.

      Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
      There is also safemalloc(). This function also has the warning that only Safefree() should be used to free pointers allocated with safemalloc(). I remember reading somewhere that the reason for Safefree(), safemalloc() and the other XS memory functions has something to do with issues involving threads. Evidently malloc() and free() can get you into trouble with threaded code. Whether or not that also means trouble with even just using a multi-threaded version of Perl albeit without user threads, I don't know.

      I used malloc in both test programs just to make them as similar as possible. The Perl XS version should use safemalloc() instead.

        There is also safemalloc()

        Yes, I've only recently become aware of its existence, and I haven't used it at all.
        I'm guessing it's just Newx() refactored to mimic the way that malloc() is called.
        If I ever see anything to suggest that it offers a significant performance improvement over Newx() then I'll probably switch to it.

        Cheers,
        Rob

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2024-03-29 02:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found