sqlite3_bind_blob什么时候可以安全释放内存?

时间:2018-01-07 15:16:07

标签: c sqlite

我有这样的工作代码:

const char sql[] = "INSERT INTO test (pk, geom) VALUES (?, ?)";
sqlite3_stmt *stmt;
sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);

for (...) {
        sqlite3_reset (stmt);
        sqlite3_clear_bindings (stmt);
        int blob_size = ..;
        unsigned char *blob = malloc(blob_size);
        sqlite3_bind_int64 (stmt, 1, pk);
        sqlite3_bind_blob (stmt, 2, blob, blob_size, free);
        sqlite3_step (stmt);
}

我想知道是否有可能不在每个循环步骤中分配和释放? 如果我将SQLITE_STATIC而不是free传递给sqlite3_bind_blob 并在周期结束后调用free此代码是否仍然有效?

const char sql[] = "INSERT INTO test (pk, geom) VALUES (?, ?)";
sqlite3_stmt *stmt;
sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL);
int capacity = 1024;
unsigned char *blob = malloc(capacity);

for (...) {
        sqlite3_reset (stmt);
        sqlite3_clear_bindings (stmt);
        int blob_size = ..;
        if (capacity < blob_size) {
           blob = realloc(blob, blob_size);
           capacity = blob_size;
        }
        sqlite3_bind_int64 (stmt, 1, pk);
        sqlite3_bind_blob (stmt, 2, blob, blob_size, SQLITE_STATIC);
        sqlite3_step (stmt);
}
free(blob);

3 个答案:

答案 0 :(得分:1)

使用boolean Namestr=(preferences.getBoolean("Name",false)); 要求该值保持有效,只要该语句可以访问它。

您的代码应该有效;但可以肯定的是,将调用移至SQLITE_STATIC(并重置)到循环结束。

答案 1 :(得分:1)

问题:如果我在周期结束后将SQLITE_STATIC而不是free传递给sqlite3_bind_blob并致电free,此代码是否仍然有效?

答案:

SQLite documentation on sqlite3_bind_blob()

如果第五个参数的值是SQLITE_TRANSIENT,则SQLite会在sqlite3_bind _ *()例程返回之前立即创建其自己的数据私有副本。

这意味着当第五个参数不具有该值时(尤其是当第五个参数具有值SQLITE_STATIC时),SQLite在例程返回后仍可能需要数据。在那种情况下,不能保证SQLite可能需要多长时间(除非,在调用sqlite3_close()之后,SQLite不需要任何东西)。

答案 2 :(得分:0)

来自SQLite docs

  

BLOB和字符串绑定接口的第五个参数是一个析构函数,用于在SQLite完成后处理BLOB或字符串。即使对绑定API的调用失败,也会调用析构函数来处置BLOB或字符串。如果第五个参数是特殊值SQLITE_STATIC,那么SQLite假定信息在静态的非托管空间中,并且不需要释放。如果第五个参数的值为SQLITE_TRANSIENT,则SQLite会在sqlite3_bind _ *()例程返回之前立即创建自己的数据私有副本。

如果要重新分配内存,则应使用SQLITE_TRANSIENT。这样,SQLite就不会做出任何关于能够依赖该内存的假设,它会自己制作副本。

请注意,当调用指定的析构函数(如果有)时,文档不会对完全说什么 - 只是在SQLite完成BLOB时调用它。如果您不想使用SQLITE_TRANSIENT,那么您应 NOT 使用SQLITE_STATIC,因为SQLite可能会或可能不会假设内存在实际不可用时可用了。

相关问题