php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #53534 Incorrect call to destructor when object stored in a session
Submitted: 2010-12-13 01:57 UTC Modified: 2010-12-13 05:45 UTC
From: jstuckle at attglobal dot net Assigned:
Status: Not a bug Package: Class/Object related
PHP Version: Irrelevant OS: Irrelevant
Private report: No CVE-ID: None
 [2010-12-13 01:57 UTC] jstuckle at attglobal dot net
Description:
------------
When an object is stored in the $_SESSION variable, the destructor is still called at the end of the script.  When the object is retrieved from the $_SESSION on the next invocation, the constructor is not called, but the destructor is again called.

To duplicate, place the attached code on a web server and load it.  Then press the reload button multiple times to see the results.

Test script:
---------------
<?php
class test {
    private $construct_count = 0;
    private $destruct_count = 0;
    public function __construct() {
        $this->construct_count++;
        echo "Constructor called.<br>\n";
    }
    public function __destruct() {
        $this->destruct_count++;
        echo "Destructor called.<br>\n";
    }
}

session_start();
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">    
<title>Test Script</title>
</head>
<body>
<?php

    if (!isset($_SESSION['test'])){
        echo "Session not found<br>\n";
        $_SESSION['test'] = new Test();
    }
    else
        echo "Session found<br>\n";

    echo "<pre>\n";
    print_r($_SESSION);
    echo "</pre>\n";
?>
</body>
</html>

Expected result:
----------------
Session not found
Constructor called.

Array
(
    [test] => test Object
        (
            [construct_count:test:private] => 1
            [destruct_count:test:private] => 0
        )

)


After second and subsequent invocations:

Session found

Array
(
    [test] => test Object
        (
            [construct_count:test:private] => 1
            [destruct_count:test:private] => 0
        )

)


Actual result:
--------------
After first invocation:
Session not found
Constructor called.

Array
(
    [test] => test Object
        (
            [construct_count:test:private] => 1
            [destruct_count:test:private] => 0
        )

)

Destructor called.


After second and subsequent invocations:

Session found

Array
(
    [test] => test Object
        (
            [construct_count:test:private] => 1
            [destruct_count:test:private] => 1 
        )

)

Destructor called.

Note: destruct_called increments on each invocation.  construct_count does not.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-12-13 03:24 UTC] dtajchreber@php.net
-Status: Open +Status: Bogus
 [2010-12-13 04:00 UTC] jstuckle at attglobal dot net
This may be "expected behavior" - but it is a direct violation of OO operations.  By definition, after a call to the destructor the object is in an undefined state.  It is invalid to use this object again without reinitializing it, i.e. calling a constructor.

It is also invalid to call a destructor on an uninitialized object, so under correct operation, the destructor calls always have a 1-to-1 relationship with constructor calls.
 [2010-12-13 04:38 UTC] jstuckle at attglobal dot net
-Operating System: Windows 7 +Operating System: Irrelevant -PHP Version: 5.3.4 +PHP Version: Irrelevant
 [2010-12-13 04:38 UTC] jstuckle at attglobal dot net
Additional information - the version and OS are irrelevant for this bugs - it occurs in 5.2.x and 5.3.x versions on both Windows and Linux.

Also, the call to the destructor is invalid because the object is not being destroyed; it is being saved in the session.
 [2010-12-13 05:17 UTC] dtajchreber@php.net
You're assuming that you're storing a persistent object between requests. You're 
not. You're storing a flattened string representation of an object which is then 
inflated and reconstructed (__wakeup() allows you define the exact behavior) to 
create a new object. The original object is destroyed at the end of the request. 
This is common behavior in many languages.
 [2010-12-13 05:45 UTC] jstuckle at attglobal dot net
No, I'm not flattening any object.  PHP is doing it under the covers, but handling it correctly is PHP's responsibility.  You claim other OO languages work like this - please indicate which ones.  No other OO language I'm familiar with which operates like this - including Smalltalk, Java and C++.  Or are you talking about languages which only try to emulate some OO behaviors?

Whether __wakeup() is called or not is immaterial; the call to the destructor is incorrect in this instance.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Feb 26 15:01:29 2024 UTC