static members of internal classes

php.internals

Michael Wallner

21 years ago
Hi, I have some issues with static members of internal classes. AFAICS no extension uses them so far (did I miss something?). There seems to be missing a proper cleanup routine for the static_member hashtable in PHP-5.0 because there are mem-leaks for each property to which another value (i.e. strings) will be assigned. And in PHP-5.1 there seems to be a cleanup routine which causes a memory read error: _zval_internal_dtor(_zval_struct * 0x00f22340, char * 0x106665a0 `string', unsigned int 401) line 79 + 11 bytes _zval_internal_ptr_dtor(_zval_struct * * 0x00f222ac, char * 0x1067203c `string', unsigned int 181) line 401 + 27 bytes _zval_internal_ptr_dtor_wrapper(_zval_struct * * 0x00f222ac) line 181 + 25 bytes zend_hash_destroy(_hashtable * 0x00f20a80) line 519 + 15 bytes destroy_zend_class(_zend_class_entry * * 0x01140a6c) line 178 + 15 bytes zend_hash_destroy(_hashtable * 0x0113f2f0) line 519 + 15 bytes compiler_globals_dtor(_zend_compiler_globals * 0x00ea2870, void * * * 0x00ea1ab0) line 461 + 15 bytes tsrm_shutdown() line 180 + 34 bytes main(int 3, char * * 0x00ea1b20) line 1152 + 8 bytes mainCRTStartup() line 338 + 17 bytes KERNEL32! 77e9893d() Thanks for any insight!
-- Michael - < mike(@)php.net >

Michael Wallner

21 years ago
I wrote:
> I have some issues with static members of internal classes. > AFAICS no extension uses them so far (did I miss something?).
I cannot declare static properties as strings because that causes memory errors in zval_dtor() (SET_STATIC_PROP_EX code is actually the same as in ReflectionClass::setStaticPropertyValue), further the strings duplicated by zval_copy_ctor() leak once. Any advice? # define GET_STATIC_PROP_EX(ce, n) zend_std_get_static_property(ce, (#n), sizeof(#n), 0 TSRMLS_CC) # define SET_STATIC_PROP_EX(ce, n, v) \ { \ int refcount; \ zend_uchar is_ref; \ zval **__static = GET_STATIC_PROP_EX(ce, n); \ \ refcount = (*__static)->refcount; \ is_ref = (*__static)->is_ref; \ zval_dtor(*__static); \ **__static = *(v); \ zval_copy_ctor(*__static); \ (*__static)->refcount = refcount; \ (*__static)->is_ref = is_ref; \ } Thanks,
-- Michael - < mike(@)php.net >

Michael Wallner

21 years ago
Hi I wrote:
> I wrote: > > >>I have some issues with static members of internal classes. >>AFAICS no extension uses them so far (did I miss something?). > > I cannot declare static properties as strings because that causes > memory errors in zval_dtor() (SET_STATIC_PROP_EX code is actually > the same as in ReflectionClass::setStaticPropertyValue), further > the strings duplicated by zval_copy_ctor() leak once.
Finally it seems to boil down to property initialization. ZE uses malloc/free for ZEND_INTERNAL_CLASS' properties while the properties contents will most likely be replaced with emalloc()'d addresses. I think the line zend_hash_init(zo->properties, 0, NULL, ZVAL_PTR_DTOR, 0); in the class ctor is pretty common, but for static properties it is zend_hash_init_ex(ce->static_members, 0, NULL, ZVAL_INTERNAL_PTR_DTOR, persistent_hashes, 0); in zend_initialize_class_data(). I'm quite puzzled now, because zend_declare_property() also uses malloc instead of emalloc() for non-static properties. Do I need to omit e[memfunc]() for static properties? Is it even a bug? Do I need to go to bed? Thanks,
-- Michael - < mike(@)php.net >

Dmitry Stogov

21 years ago
Hi Michael, It is not a bug. You understood proper. Internal classes are stored in regular heap and they don't use e[memory] function family. This is done, because memory allocated by emalloc is freed after each request, but internal classes should still alive in global class table. Thanks. Dmitry.

Michael Wallner

21 years ago
Hi Dmitry Stogov, you wrote:
> Hi Michael, > > It is not a bug. You understood proper. Internal classes are stored in > regular heap and they don't use e[memory] function family. > This is done, because memory allocated by emalloc is freed after each > request, but internal classes should still alive in global class table.
Thank you very much for your answer, Dmitry. I guess I got the clue now -- that basically means, that I must not use e[memfuncs] for static properties, right? Isn't the behaviour of ReflectionClass then bogus, because it doesn't care about ZEND_INTERNAL_CLASSes? May I suggest, that the zend engine provides some more sophisticated routines to modify/retreive static poperties, i.e. "transformation" from dynamic zvals to internal ones? Thanks a lot,
-- Michael - < mike(@)php.net >

Michael Wallner

21 years ago
Hi, I wrote:
> Isn't the behaviour of ReflectionClass then bogus, because > it doesn't care about ZEND_INTERNAL_CLASSes?
And... shouldn't there be a cleanup for static members of ZEND_INTERNAL_CLASSes to reset the contents to the declared values? Also zval_internal_dtor() implies that one cannot set a static member of a ZEND_INTERNAL_CLASS to be a stream, array etc... Thanks,
-- Michael - < mike(@)php.net >

Andi Gutmans

21 years ago
At 09:50 AM 7/22/2005 +0200, Michael Wallner wrote:
>Also zval_internal_dtor() implies that one cannot set >a static member of a ZEND_INTERNAL_CLASS to be a stream, >array etc...
Yes, that's correct. It's a limitation you have to live with because those datastructures are destroyed at the end of the request. That said, you can create them at RINIT/RSHUTDOWN. Unless you are doing something exceptionally big, it shouldn't be a biggy. Andi

Michael Wallner

21 years ago
Hi Andi Gutmans, you wrote:
>> Also zval_internal_dtor() implies that one cannot set >> a static member of a ZEND_INTERNAL_CLASS to be a stream, >> array etc... > > > Yes, that's correct. It's a limitation you have to live with because > those datastructures are destroyed at the end of the request. That said, > you can create them at RINIT/RSHUTDOWN. Unless you are doing something > exceptionally big, it shouldn't be a biggy.
Yes, I was actually concerned about the in-request exchange, but I'm already doing that by hand now, thanks. Regards,
-- Michael - < mike(@)php.net >

Marcus Boerger

21 years ago
Hello Michael, sure but there's a difference Reflection whatever is only run during request time, what you want is running outside and require malloc rather than emalloc. Thursday, July 21, 2005, 4:30:59 PM, you wrote:
> I wrote:
>> I have some issues with static members of internal classes. >> AFAICS no extension uses them so far (did I miss something?).
> I cannot declare static properties as strings because that causes > memory errors in zval_dtor() (SET_STATIC_PROP_EX code is actually > the same as in ReflectionClass::setStaticPropertyValue), further > the strings duplicated by zval_copy_ctor() leak once.
> Any advice?
> # define GET_STATIC_PROP_EX(ce, n) > zend_std_get_static_property(ce, (#n), sizeof(#n), 0 TSRMLS_CC) > # define SET_STATIC_PROP_EX(ce, n, v) \ > { \ > int refcount; \ > zend_uchar is_ref; \ > zval **__static = GET_STATIC_PROP_EX(ce, n); \ > \ > refcount = (*__static)->refcount; \ > is_ref = (*__static)->is_ref; \ > zval_dtor(*__static); \ > **__static = *(v); \ > zval_copy_ctor(*__static); \ > (*__static)->refcount = refcount; \ > (*__static)->is_ref = is_ref; \ > }
> Thanks, > -- > Michael - < mike(@)php.net >
-- Best regards, Marcus mailto:mail@marcus-boerger.de

Michael Wallner

21 years ago
Hi Marcus Boerger, you wrote:
> Hello Michael, > > sure but there's a difference Reflection whatever is only run during > request time, what you want is running outside and require malloc rather > than emalloc.
Thanks, I already adjusted my code according to that. But guess, I've still not solved all my problems :( D:\Daten\Source\php-src>Debug_TS\php.exe -r "ReflectionClass::export(HttpResponse);" | grep dummy Property [ public static $dummy ] D:\Daten\Source\php-src>Debug_TS\php.exe -r "$c = new ReflectionClass(HttpResponse); $c->setStaticPropertyValue('dummy', 'foobar');" Fatal error: Uncaught exception 'ReflectionException' with message 'Class HttpResponse does not have a property named dummy' in Command line code:1 D:\Daten\Source\php-src>Debug_TS\php.exe -r "echo HttpResponse::$dummy;" Fatal error: Access to undeclared static property: HttpResponse::$dummy in Command line code on line 1 The static property "dummy" is declared as follows: zend_declare_property_string(http_response_object_ce, "dummy", sizeof("dummy"), "EMPTY", ZEND_ACC_PUBLIC|ZEND_ACC_STATIC TSRMLS_CC); Thanks,
-- Michael - < mike(@)php.net >