PHP 4.0 Bug #8222: Objects are not automatically destroyed when reference count=0
| From: | christian dot niss at avinci dot de | Date: | Wed, 13 Dec 2000 10:44:12 +0000 |
| Subject: | PHP 4.0 Bug #8222: Objects are not automatically destroyed when reference count=0 | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-41145@lists.php.net to get a copy of this message | ||
From: christian.niss@avinci.de
Operating system: Linux 2.2.16
PHP version: 4.0.3pl1
PHP Bug Type: Class/Object related
Bug description: Objects are not automatically destroyed when reference count=0
Hi there,
as there are no extentions returning objects, perhaps I am the first to encounter following problem:
I wrote an extention with functions returning objects. The problem is that these objects are not
automatically destroyed in memory when no variable references them anymore.
A script like the following causes php to consume more and more memory until it terminates with
"out of memory" ...
01:<?
02: [...]
03: while ($i++ < 10000)
04: {
05: $result=k2_searchrecv($a,$b,$c,$d,$e);
06: }
07: [...]
08:
09:?>
Even if I change line 05 to
05: k2_searchrecv($a,$b,$c,$d,$e);
so that the resulting object is not referenced by any variable, memory consumption grows.
one resulting objects looks like:
object(stdClass)(9) {
["errorCode"]=>
int(0)
["errorMessage"]=>
string(1) "-"
["docStart"]=>
int(1)
["docPage"]=>
int(6)
["numHit"]=>
int(6)
["numProc"]=>
int(52672)
["numCols"]=>
int(3)
["numRows"]=>
int(6)
["square"]=>
array(6) {
[0]=>
object(stdClass)(3) {
["SCORE"]=>
string(6) "0.7742"
["VdkVgwKey"]=>
string(6) "401824"
["JOB_TITLE"]=>
string(44) "Software-Entwickler/in Information Retrieval"
}
[1]=>
object(stdClass)(3) {
["SCORE"]=>
string(6) "0.7742"
["VdkVgwKey"]=>
string(6) "384327"
["JOB_TITLE"]=>
string(18) "UNIX-Administrator"
}
[2]=>
object(stdClass)(3) {
["SCORE"]=>
string(6) "0.7742"
["VdkVgwKey"]=>
string(6) "396529"
["JOB_TITLE"]=>
string(38) "SoftwareentwicklerInnen-architektInnen"
}
[3]=>
object(stdClass)(3) {
["SCORE"]=>
string(6) "0.7742"
["VdkVgwKey"]=>
string(6) "314928"
["JOB_TITLE"]=>
string(27) "Anwendungsprogrammierer(in)"
}
[4]=>
object(stdClass)(3) {
["SCORE"]=>
string(6) "0.7742"
["VdkVgwKey"]=>
string(8) "10017461"
["JOB_TITLE"]=>
string(41) "Praktikant oder studentischer Mitarbeiter"
}
[5]=>
object(stdClass)(3) {
["SCORE"]=>
string(6) "0.7742"
["VdkVgwKey"]=>
string(6) "239921"
["JOB_TITLE"]=>
string(38) "Internet/Intranet/Extranet-Consultants"
}
}
}
Could the problem be, that the object-type is stdClass and not a user-defined class ?
Here one function that builds an object as result:
------------------------------------------------------------
PHP_FUNCTION(k2_searchrecv)
{
zval **shandle, **docstart, **docpage, **timeout, **fieldnames;
zval **ksquare=0 ,***dummyzval=0 ;
K2Error kerror;
char *dummyptr;
char **fieldnamearray = 0;
int i,j;
int fieldcount;
int withfieldnames = 0;
int retries = 0;
char *dummystring;
K2SearchRecvOut recvOut = 0;
K2SearchRecvArgRec recvNew;
switch(ZEND_NUM_ARGS())
{
case 4: {
if (zend_get_parameters_ex(4, &shandle, &docstart, &docpage, &timeout) ==
FAILURE)
RETURN_LONG(-1);
break;}
case 5: {
if (zend_get_parameters_ex(5, &shandle, &docstart, &docpage, &timeout,
&fieldnames) == FAILURE)
RETURN_LONG(-1);
withfieldnames = 1;
dummystring = estrdup((*fieldnames)->value.str.val);
fieldcount = k2_internal_getNoOfStrings(dummystring);
dummyptr = dummystring;
fieldnamearray=(char**) emalloc (sizeof(char*) * fieldcount);
if (fieldnamearray == NULL)
{
php_error(E_ERROR,"k2_searchrecv: Unable to allocate memory for
'fieldnamearray'");
return;
}
for (j=0; j < fieldcount; j++)
{
fieldnamearray[j]=estrdup(dummyptr);
dummyptr = dummyptr + strlen(dummyptr)+1;
}
efree(dummystring);
break;}
default: WRONG_PARAM_COUNT;
}
convert_to_long_ex(shandle);
convert_to_long_ex(docstart);
convert_to_long_ex(docpage);
convert_to_long_ex(timeout);
K2StructInit(&recvNew);
recvNew.docStart = (*docstart)->value.lval;
recvNew.docPage = (*docpage)->value.lval;
recvNew.timeout = (*timeout)->value.lval;
if ((kerror=K2SearchRecv((K2Search)(*shandle)->value.lval,&recvNew,&recvOut)) !=
K2Success)
{
if (kerror == 1)
{
usleep(100);
while ((kerror=K2SearchRecv((K2Search)(*shandle)->value.lval,&recvNew,&recvOut) !=
K2Success) &&
(retries < MAX_RETRIES))
{
usleep(100);
retries++;
}
}
if (kerror != K2Success) RETURN_LONG(kerror);
}
if (object_init(return_value) == FAILURE) {
php_error(E_ERROR, "k2_searchrecv: Unable to initialize 'return_value' as
object");
return -1;
}
add_property_long(return_value,"errorCode", recvOut->errorCode);
if (recvOut->errorMessage) {
add_property_string(return_value,"errorMessage",recvOut->errorMessage,1);
} else { add_property_string(return_value,"errorMessage","-",1); }
add_property_long(return_value,"docStart",recvOut->docStart);
add_property_long(return_value,"docPage",recvOut->docPage);
add_property_long(return_value,"numHit",recvOut->numHit);
add_property_long(return_value,"numProc",recvOut->numProc);
if (recvOut->square)
{
add_property_long(return_value,"numCols",recvOut->square->numCols);
add_property_long(return_value,"numRows",recvOut->square->numRows);
ksquare = (zval **) emalloc (sizeof(zval*));
dummyzval = (zval ***) emalloc(sizeof(zval**));
*dummyzval = (zval *) emalloc(sizeof(zval *));
*ksquare = (zval*) emalloc (sizeof(zval));
if ( array_init(*ksquare) == FAILURE ) {
php_error(E_ERROR,"k2_searchrecv: Unable to initialize '*ksquare' as
object");
return;
}
dummyptr = (char*) recvOut->square->pData;
for(i=0; i < recvOut->square->numRows; i++)
{
// create one element of the result list including all specified fields
*dummyzval=(zval**) emalloc(sizeof(zval*));
**dummyzval= (zval*) emalloc(sizeof(zval));
if (**dummyzval == NULL) {
php_error(E_ERROR, "k2_searchrecv: Unable to allocate memory for
'**dummyzval'");
}
if (withfieldnames == 0) {
if (array_init(**dummyzval) == FAILURE) {
php_error(E_ERROR, "k2_searchrecv: Unable to initialize '**dummyzval' as
array");
return;
}
}
else {
if (object_init(**dummyzval) == FAILURE) {
php_error(E_ERROR, "k2_searchrecv: Unable to initialize '**dummyzval' as
object");
return;
}
}
for(j=0; j < recvOut->square->numCols; j++)
{
if (withfieldnames == 0) { add_next_index_string(**dummyzval,dummyptr,1);}
else {add_property_string(**dummyzval,fieldnamearray[j],dummyptr,1);}
// printf("%d: %p[%d] -> %s \n",i,**dummyzval,j,dummyptr);
dummyptr = dummyptr + strlen(dummyptr) + 1; //printf("j=%d - %s\n",j,dummyptr);
}
// append
zend_hash_next_index_insert((*ksquare)->value.ht,*dummyzval,sizeof(zval*),NULL);
}
// append all the results in ksquare to the return structure
zend_hash_add(return_value->value.obj.properties,"square",strlen("square")+1,
(void*) ksquare,sizeof (zval*),NULL);
} else {
add_property_long(return_value,"numCols",0);
add_property_long(return_value,"numRows",0);
}
//clean up
K2SearchRecvFree(recvOut);
if (withfieldnames) {
for (i=0; i < fieldcount; i++)
efree(fieldnamearray[i]);
efree(fieldnamearray);
}
}
------------------------------------------------------------
TIA
CHristian
--
Edit Bug report at: http://bugs.php.net/?id=8222&edit=1