我有这样的工作守则:
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);
发布于 2018-01-07 17:01:43
使用SQLITE_STATIC
需要该值保持有效,只要语句可以访问它。
您的代码应该是有效的;但是要确定的是,将对sqlite3_clear_bindings()
的调用(和重置)移到循环的末尾。
发布于 2020-10-21 13:25:03
问题:如果我在循环结束后通过SQLITE_STATIC
free
而不是free
到 sqlite3_bind_blob
并调用 free
,那么该代码是否仍然有效?< code >E 221
答:No.
如果第五个参数的值为SQLITE_TRANSIENT,那么SQLite将在sqlite3_bind_*()例程返回之前立即创建自己的数据私有副本。
这意味着当第五个参数没有这个值时(特别是当第五个参数具有SQLITE_STATIC
值时),SQLite可能在例程返回之后仍然需要数据。在这种情况下,不保证SQLite可能需要多长时间的数据(除非,SQLite在调用sqlite3_close()
之后不需要任何东西)。
发布于 2018-01-07 17:10:55
来自SQLite 文档
BLOB和string绑定接口的第五个参数是一个析构函数,用于在SQLite完成BLOB或string之后释放BLOB或string。即使绑定API调用失败,也会调用析构函数来释放BLOB或string。如果第五个参数是特殊值SQLITE_STATIC,那么SQLite假定信息位于静态的非托管空间,不需要释放。如果第五个参数的值为SQLITE_TRANSIENT,那么SQLite将在sqlite3_bind_*()例程返回之前立即创建自己的数据私有副本。
如果要重新分配内存,则应该使用SQLITE_TRANSIENT
。那样的话,SQLite就不会做任何关于能够依赖内存的假设,它会自己复制。
请注意,文档没有确切地说明何时调用指定的析构函数(如果有的话) --只是在SQLite完成BLOB时调用它。如果您不想使用SQLITE_TRANSIENT
,那么就不应该使用SQLITE_STATIC
,因为当内存实际上不再可用时,SQLite可能会或者不认为它是可用的。
https://stackoverflow.com/questions/48138521
复制相似问题