在关闭准备好的语句之前在函数中返回值 - 内存泄漏?

Posted

技术标签:

【中文标题】在关闭准备好的语句之前在函数中返回值 - 内存泄漏?【英文标题】:Returning Value in Function before closing prepared statement - Memory leak? 【发布时间】:2020-10-13 09:53:50 【问题描述】:

我想确保我没有一些内存泄漏和不良编码习惯。我可能只是在这里回答自己。

这是我的一个典型功能,我应该在所有返回的情况下绑定一个$temp,然后在最后返回还是这样?

define DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_DATABASE 
$db = mysqli_connect(DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_DATABASE);

function Resolvestuff($input) 
    global $db;
    if ($stmt = $db->prepare("Select Column from Table where `a` = ?")) 
        $stmt->bind_param('s', $input);
        $stmt->execute();
        $stmt->store_result();
        $stmt->bind_result($col1);
        $row = $stmt->fetch();
        if ($stmt->num_rows == 0) 
            return "Nothing";
         else 
            return $col1;
        
        $stmt->free_result(); // i mean, is this even performed at some point ?
        $stmt->close();
     else 
        return "Nothing";
    

    //Return here instead ?

【问题讨论】:

您需要停止手动检查错误。请阅读:Should we ever check for mysqli_connect() errors manually? 和 Should I manually check for errors when calling “mysqli_stmt_prepare”? $stmt->num_rows == 0 根本不需要 【参考方案1】:

您的问题的一个简单答案是$stmt 是一个局部变量,因此 php 将在函数执行结束后立即清理它并收集垃圾。您无需致电free_resultclose

更长的答案是您从错误的角度处理这个问题。你不应该像这样创建特定的函数。你必须有一个通用函数。例如。

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$mysqli->set_charset('utf8mb4'); // always set the charset

function fetchSingle(mysqli $db, string $sql, array $params = []) 
    $stmt = $db->prepare($sql);
    if ($params) 
        $stmt->bind_param(str_repeat("s", count($params)), ...$params);
    
    $stmt->execute();
    $stmt->bind_result($col1);
    $stmt->fetch();
    return $col1;


$val = fetchSingle($mysqli, "Select Column from Table where `a` = ?", [$input]);

【讨论】:

哇,从来没想过,我真的看到了这种广泛使用功能的潜力!但是话又说回来,我会遇到一定会在我的站点中重复的 Select Statements,因此简化预制函数的形状是有意义的,不是吗? 没有。 SQL 本身就是一行代码。在函数中包装一行并不是很有用,除非您也有其他一些功能要封装。这里的关键是不应在整个代码中使用 mysqli 函数。它们必须封装在抽象层中。 mysqli 很难使用,如果可以的话,你应该使用 PDO。如果你想使用 mysqli,你需要编写这样的函数来帮助你做一些简单的事情。这是另一个很好的例子phpdelusions.net/mysqli/simple

以上是关于在关闭准备好的语句之前在函数中返回值 - 内存泄漏?的主要内容,如果未能解决你的问题,请参考以下文章

使用检查样式防止准备好的语句泄漏

Perl DBI 何时关闭准备好的语句

准备好的语句总是返回 -2 值

Block控制器传值和内存泄漏

从准备好的语句中获取数据

如何将此代码转换为准备好的语句或 jdbc 中的语句? [关闭]