PHP 4.0 Bug #8222 Updated: Objects are not automatically destroyed when reference count=0
| From: | stas@php.net | Date: | Thu, 08 Mar 2001 17:48:36 +0000 |
| Subject: | PHP 4.0 Bug #8222 Updated: Objects are not automatically destroyed when reference count=0 | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-48295@lists.php.net to get a copy of this message | ||
ID: 8222
Updated by: stas
Reported By: christian.niss@avinci.de
Old-Status: Open
Status: Feedback
Bug Type: Class/Object related
Assigned To:
Comments:
If you compile PHP in debug mode (--enable-debug) does it
report any memory leaks? If not, the leak is probably not in
PHP code, but in external code (or caused by some wrong work
with external library). If yes, please post the leaks.
Also, you could use some malloc debugging library to see if
there aren't some leaks external to PHP.
Previous Comments:
---------------------------------------------------------------------------
[2000-12-13 05:44:12] christian.niss@avinci.de
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 - %sn",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
---------------------------------------------------------------------------
ATTENTION! Do NOT reply to this email!
To reply, use the web interface found at http://bugs.php.net/?id=8222&edit=2