在使用PDO实例执行查询时获取分段错误

问题描述 投票:2回答:1

使用PDO实例执行查询时,脚本会产生分段错误。在验证PDO对象确实是PDO类的实例之后会发生这种情况:

var_dump($db)

结果导致:

Object(PDO)#16 {
}

它还可以在实例化对象后立即成功执行没有分段错误的查询,但不会在稍后的脚本中执行。

php mysql pdo segmentation-fault
1个回答
2
投票

这个问题最终成为了PHP对象的怪癖,也是一个试图过于聪明的开发人员。

在PHP中,对象通过引用(排序)传递到所有范围。这意味着子范围可以更改父范围中的对象。为了避免这种情况,我正在处理的程序将对象存储在一个值存储中,如果它是一个对象,这个值存储将在返回它之前克隆该变量:

    public function getConfig(string $key)
    {
        if ($this->hasConfig($key) === true) {
            if (is_object($this->configValues[$key]) === true) {
                return clone $this->configValues[$key];
            } else {
                return $this->configValues[$key];
            }
        } else {
            return null;
        }
    }

clone关键字(详细的here)创建对象及其属性的浅表副本,同时保留所有属性作为引用。

但是,当克隆PDO对象时,它不会维护允许它连接到数据库的流处理程序,但它确实维护了引用。

不幸的是,这会导致分段错误。

我怀疑这是因为内部超出范围(受保护)的内存被访问,或者因为实际上允许PHP与PDO与MySQL /数据库通信的库不允许以这种方式传递流处理程序。

无论原因如何,如果您克隆PDO对象然后使用它进行查询,它将导致不会产生错误或异常的分段错误,从而允许您调试问题。

必须始终传递和使用实际的数据库对象。

我创建了这个问题和答案来记录这个特殊的怪癖,因为当我最初尝试调试问题时,我无法在Google上找到任何关于此特定行为的引用。

在PHP 7.2.16中观察到此行为,我还没有验证它是否会在其他版本的PHP中产生类似的行为。

如果无法以这种方式安全地克隆流处理程序,则预期的行为是clone关键字在PDO对象上使用时抛出异常。

编辑:

可能有贡献的另一个因素(同样,这不是我广泛测试的)是这个特定的连接使用PDO::MYSQL_ATTR_SSL_CA属性来设置SSL证书.pem文件。

© www.soinside.com 2019 - 2024. All rights reserved.