为什么这个类导致内存泄漏?

时间:2017-05-09 13:20:47

标签: php

我已将配置库导入到我的项目中,以便我可以轻松地使用PHP管理数据文件。

/**
 * Config Class for simple config manipulation of multiple formats.
 */
class Config{
    const DETECT = -1; //Detect by file extension
    const PROPERTIES = 0; // .properties
    const CNF = Config::PROPERTIES; // .cnf
    const JSON = 1; // .js, .json
    const YAML = 2; // .yml, .yaml
    //const EXPORT = 3; // .export, .xport
    const SERIALIZED = 4; // .sl
    const ENUM = 5; // .txt, .list, .enum
    const ENUMERATION = Config::ENUM;
    /** @var array */
    private $config = [];
    private $nestedCache = [];
    /** @var string */
    private $file;
    /** @var bool */
    private $correct = false;
    /** @var int */
    private $type = Config::DETECT;
    /** @var int */
    private $jsonOptions = JSON_PRETTY_PRINT | JSON_BIGINT_AS_STRING;
    public static $formats = [
        "properties" => Config::PROPERTIES,
        "cnf" => Config::CNF,
        "conf" => Config::CNF,
        "config" => Config::CNF,
        "json" => Config::JSON,
        "js" => Config::JSON,
        "yml" => Config::YAML,
        "yaml" => Config::YAML,
        //"export" => Config::EXPORT,
        //"xport" => Config::EXPORT,
        "sl" => Config::SERIALIZED,
        "serialize" => Config::SERIALIZED,
        "txt" => Config::ENUM,
        "list" => Config::ENUM,
        "enum" => Config::ENUM,
    ];

    /**
     * @param string $file     Path of the file to be loaded
     * @param int    $type     Config type to load, -1 by default (detect)
     * @param array  $default  Array with the default values that will be written to the file if it did not exist
     * @param null   &$correct Sets correct to true if everything has been loaded correctly
     */
    public function __construct($file, $type = Config::DETECT, $default = [], &$correct = null){
        $this->load($file, $type, $default);
        $correct = $this->correct;
    }

    /**
     * @param $k
     * @param $v
     */
    public function __set($k, $v){
        $this->set($k, $v);
    }

    public function set($k, $v = true){
        $this->config[$k] = $v;
        foreach($this->nestedCache as $nestedKey => $nvalue){
            if(substr($nestedKey, 0, strlen($k) + 1) === ($k . ".")){
                unset($this->nestedCache[$nestedKey]);
            }
        }
    }

    /**
     * @param       $k
     * @param mixed $default
     *
     * @return bool|mixed
     */
    public function get($k, $default = false){
        return ($this->correct and isset($this->config[$k])) ? $this->config[$k] : $default;
    }
    /**
 * @param       $file
 * @param int   $type
 * @param array $default
 *
 * @return bool
 */

public function load($file, $type = Config::DETECT, $default = []){
    $this->correct = true;
    $this->type = (int) $type;
    $this->file = $file;
    if(!is_array($default)){
        $default = [];
    }
    if(!file_exists($file)){
        $this->config = $default;
        $this->save();
    }else{
        if($this->type === Config::DETECT){
            $extension = explode(".", basename($this->file));
            $extension = strtolower(trim(array_pop($extension)));
            if(isset(Config::$formats[$extension])){
                $this->type = Config::$formats[$extension];
            }else{
                $this->correct = false;
            }
        }
        if($this->correct === true){
            $content = file_get_contents($this->file);
            switch($this->type){
                case Config::PROPERTIES:
                case Config::CNF:
                    $this->parseProperties($content);
                    break;
                case Config::JSON:
                    $this->config = json_decode($content, true);
                    break;
                case Config::YAML:
                    $content = self::fixYAMLIndexes($content);
                    $this->config = yaml_parse($content);
                    break;
                case Config::SERIALIZED:
                    $this->config = unserialize($content);
                    break;
                case Config::ENUM:
                    $this->parseList($content);
                    break;
                default:
                    $this->correct = false;
                    return false;
            }
            if(!is_array($this->config)){
                $this->config = $default;
            }
            if($this->fillDefaults($default, $this->config) > 0){
                $this->save();
            }
        }else{
            return false;
        }
    }
    return true;
}

在我的脚本中,启用gc_enable()后,我使用此类创建了一些数据文件。

$data = new Config($this->path . "file.yml", Config::YAML);
$data->set("key", "this will leak memory");

我从未保存对$ data的任何引用,但我的系统正在泄漏内存。我不知道为什么PHP会将内存泄漏给没有引用的对象。什么可能导致此内存泄漏?

0 个答案:

没有答案