我有这样的工作代码:
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);
答案 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可能会或可能不会假设内存在实际不可用时可用了。