gpt4 book ai didi

php7、引用文献和 oci_bind_by_name

转载 作者:搜寻专家 更新时间:2023-10-31 21:24:43 24 4
gpt4 key购买 nike

我在 php.net 之前将此发布在这里,以便更好地理解我在 PHP 5.x 和 7.x 之间看到的行为差异。

以下代码适用于 PHP 5.x 但不适用于 7.x

$conn = oci_connect('****', '****', '****', '****');
$stmt = oci_parse($conn, 'select record# from company where record#=:1');

$cache = [];

$cacheRow[0] = '2270';

oci_bind_by_name($stmt, ":1", $cacheRow[0], 2*strlen($cacheRow[0])+32);

$cache[0] = $cacheRow;

$result = runStmt($stmt);
checkResult($result, '2270');

$cacheRow = $cache[0];
$cacheRow[0] = '2274';
$cache[0] = $cacheRow;

$result = runStmt($stmt);
checkResult($result, '2274');

runStmt() 只是 oci_execute 和 oci_fetch_array。 checkResult() 只是验证返回的行是否包含第二个参数中的值。

在 PHP 7(无论如何是 7.0.8 和 7.0.10)中,对 checkResult 的第二次调用报告返回的行包含 RECORD# 2270 而不是预期的 2274。

跟踪 gdb 中的代码,这是我拼凑的内容:

  • oci_bind_by_name 的 &$variable 参数最终被 z/取消引用,并在 bindp->zval (oci8_statement.c:1250) 中作为一个简单的字符串 zval 继续存在。这没关系,因为只要所有 zval 都指向同一个字符串,其他更简单的测试就可以工作。

  • 从 oci_bind_by_name 返回时,$cacheRow[0] 现在是预期的引用。

  • 在下一个 $cacheRow[0] = '2274' 时,当 $cacheRow 的副本在赋值期间创建时,生成的副本中的 $cacheRow[0] 不再是引用,只是一个指向的 zval原始字符串。

  • 复制后,当分配到新的 $cacheRow[0] 时,它只是更改其 str 指针。

现在新的 $cacheRow[0] 指向与 oci8_statement 的 bindp->zval 不同的字符串,因此下一个 oci_execute 将提取旧的绑定(bind)值。

我可以通过确保涉及 $cache[0] 的分配(输入到和输出)是通过引用来解决这个问题。这避免了这个问题,因为 $cacheRow 数组永远不会分开。

我也可以用纯 PHP 代码重现它

function bbn1(&$var)
{
}

function test1()
{
$cache = [];

$cacheRow[0] = '2270';

bbn1($cacheRow[0]);
$x = $cacheRow[0];

$cache[0] = $cacheRow;

$cacheRow = $cache[0];
// Copy-on-write of $cacheRow does not preserve the reference in
// $cacheRow[0] because $cacheRow[0]'s refcount == 1
// zend_array_dup_element in zend_hash.c
$cacheRow[0] = '2274';

}

function bbn2(&$var)
{
static $cache = [];
$cache[] =& $var;
}

function test2()
{
$cache = [];

$cacheRow[0] = '2270';

bbn2($cacheRow[0]);
$x = $cacheRow[0];

$cache[0] = $cacheRow;

$cacheRow = $cache[0];

// Copy-on-write of $cacheRow preserves the reference in
// $cacheRow[0] because $cacheRow[0]'s refcount != 1
// zend_array_dup_element in zend_hash.c
$cacheRow[0] = '2274';

}

因为我可以在纯 PHP 测试中获得不同的行为,具体取决于我是否保留对传递给 bbn 的参数的引用,这让我认为如果 oci_bind_by_name 增加了其传入的 bind_var 参数的引用计数,我的原始测试在 PHP 之间的行为将相同5 和 PHP 7。话又说回来,我愿意相信这是预期的行为,我确实需要使用 assignment-by-ref。

最佳答案

关于php7、引用文献和 oci_bind_by_name,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38861588/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com