Alex K
Alex K

Reputation: 21

PHP C Extension Global Memory Management

I'm writing a C extension that should allocate a global array when the module inits (that array doesn't change and is relevant for every request). I've read about php c extensions memory management, but most sources don't mention declaring variables on the stack.

Is that still a valid approach, or is it more likely to leak in which case I should prefer pemalloc, etc...?

Some sample code to illustrate the question:
In my header:

ZEND_BEGIN_MODULE_GLOBALS(myExtension)
long long myArray[ARRAY_SIZE];
ZEND_END_MODULE_GLOBALS(myExtension)

And in the implementation:

PHP_MINIT_FUNCTION(myExtension) {
    fillUpMyArray();
    return SUCCESS;
}

Thanks,
Alex

Upvotes: 2

Views: 690

Answers (1)

klaus triendl
klaus triendl

Reputation: 1369

There are basically two different kinds of memory usage from within a php extension:

  • thread-local storage, which in zend-speak are "thread safe global" variables, usable during a specific request;
    needs to be set up in ZEND_GINIT_FUNCTION(myExtension) and torn down in ZEND_GSHUTDOWN_FUNCTION(myExtension) [available when ZEND_MODULE_API_NO >=20060613, php >=5.2.0]
  • process-wide storage, which is referred to with the term "persistent data";
    needs to be set up statically and/or in ZEND_MINIT_FUNCTION(myExtension) and torn down statically and/or in ZEND_MSHUTDOWN_FUNCTION(myExtension)

With the ZEND_BEGIN_MODULE_GLOBALS macro you declare thread safe global variables, what you really want is persistent data.

(!) Please note that php only knows the data type long, not long long.

What you don't tell is how exactly you're using you array.
For your specific case you could simply use a static array, defined in your .c/.cpp file, plus an array access function:

static long myArray[ARRAY_SIZE];

ZEND_MINIT_FUNCTION(myExtension)
{
    fillUpMyArray();
    return SUCCESS;
}

ZEND_FUNCTION(myext_get)
{
    long idx;

    if (zend_parse_parameters_ex(0, ZEND_NUM_ARGS() TSRMLS_CC, "l", &idx) == FAILURE)
        RETURN_NULL();

    // TODO check array bounds!

    RETURN_LONG(myArray[idx]);
}

Upvotes: 2

Related Questions