php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #18494 DB::query leaks memory
Submitted: 2002-07-23 11:13 UTC Modified: 2003-06-11 12:10 UTC
From: sam at ananova dot com Assigned: ssb (profile)
Status: Closed Package: PEAR related
PHP Version: 4.2.0 OS: linux redhat 7.3 up2date-ed
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: sam at ananova dot com
New email:
PHP Version: OS:

 

 [2002-07-23 11:13 UTC] sam at ananova dot com
  $result=$this->db->query($sql,$values);
 
makes use of "prepare" internally and doesn't free the results.
 
e.g., the following script, does one query 5 times and annother time with different values, yet when done, diagnose() prints out that 6 lots of prepare_tokens, prepare_types, prepare_queries were stored in the db object!

I reckon at least they should have been destroyed when the results were destroyed (if no results, then right away!).

<?php

include_once("DB.php");

$_db=array(
    'phptype'  => "pgsql",
    'hostspec' => "localhost",
    'database' => "*****",
    'username' => "*******",
    'protocol' => "unix",
    'password' => "***********");

$db=DB::connect($_db);
if (DB::isError($db)) {
  die("Can't connect");
}

$sql="select ?";
QUERY($db,$sql,array(1));
QUERY($db,$sql,array(1));
QUERY($db,$sql,array(1));
QUERY($db,$sql,array(1));
QUERY($db,$sql,array(1));
QUERY($db,$sql,array(2));

var_dump($db);
diagnose($db);

function diagnose(&$db) {
  foreach($db as $key=>$val) if (eregi('^prepare',$key) && is_array($val)) {
    print count($val). " of $key\n";
  }
}

function QUERY(&$db,$sql,$array) {
  $result=$db->query($sql,array(1));
  if (DB::isError($result)) {
    die ("Dead: ".$result->userinfo);
  }
  $numRows=$result->numRows();
  if ($numRows>1) die ("Too many matches for $query,");
  if ($numRows) {
    $data=$result->fetchRow(DB_FETCHMODE_ASSOC);
  }
  if (is_object($result)) $result->free();
  return $data;
}
?>


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-04-28 04:01 UTC] arnaud@php.net
changing status
 [2003-05-04 12:16 UTC] lsmith@php.net
I think this is a general problem with the various methods in PEAR::DB that prepare and execute in one go and return a result set. This way the user never gets the prepared "id". Therefore PEAR::DB should free these for the user (since the user can't use the id again anyways).

Like so:
733c733,735
<             return $this->execute($sth, $params);
---
>             $result = $this->execute($sth, $params);
>             $this->freeResult($sth);
>             return $result;

But somebody has to go through and probably look at every instance of return $this->execute() where the user did not pass a prepare ID. (Did I mention before that this is imho is abuse of prepare/execute and if you want this sort of seperation of data and query structure you should use a layer ontop of PEAR::DB .. my 2 cents)
 [2003-06-11 12:10 UTC] cox@php.net
I've fixed that, avaible in CVS, by adding a new $db_object->freePrepared() method and calling it from all the functions that doesn't expose the prepared statement.

Thanks for reporting
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sat May 10 07:01:29 2025 UTC