gpt4 book ai didi

c++ - 在 SQLite 中使用 blob 时如何处理类型错误?

转载 作者:行者123 更新时间:2023-11-28 06:11:47 25 4
gpt4 key购买 nike

在 SQLite 中使用 blob 时,是否有处理类型错误的好方法?例如,下面的代码注册了两个函数create_vectordisplay_vector。基本上,create_vectorstd::vector 存储为 blob,display_vector 将此 blob 转换为文本,以便我们可以看到它:

/* In order to use

sqlite> .load "./blob.so"
sqlite> select display_vector(create_vector());
[ 1.200000, 3.400000, 5.600000, 7.800000, 9.100000 ]

*/

#include <string>
#include <sqlite3ext.h>
SQLITE_EXTENSION_INIT1

extern "C" {
int sqlite3_blob_init(
sqlite3 * db,
char ** err,
sqlite3_api_routines const * const api
);
}

// Cleanup handler that deletes an array
template <typename T>
void array_cleanup(void * v) {
delete [] static_cast <T *> (v);
}

// Creates and returns a std::vector as a blob
static void create_vector(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
// Create a dummy vector
auto * v = new double[5] {1.2,3.4,5.6,7.8,9.10};

// Either cleanup works
sqlite3_result_blob(context,v,sizeof(double[5]),array_cleanup <double>);
}

// Converts a std::vector into text
static void display_vector(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
// Grab the vector. Note, if this is not a vector, then sqlite will
// almost certainly segfault.
auto const * const v =static_cast <double const * const> (
sqlite3_value_blob(argv[0]));

// Assuming we have a vector, convert it into a string
auto s = std::string("[ ");
for(unsigned i=0;i<5;i++) {
// If we're not on the first element, add a comma
if(i>0) s += ", ";

// Add the number
s += std::to_string(v[i]);
}
s += " ]";

// Return the text
sqlite3_result_text(
context,sqlite3_mprintf("%s",s.c_str()),s.size(),sqlite3_free);
}

// Register our blob functions
int sqlite3_blob_init(
sqlite3 *db,
char **err,
sqlite3_api_routines const * const api
){
SQLITE_EXTENSION_INIT2(api)

// Register the create_vector function
if( int ret = sqlite3_create_function(
db, "create_vector", 0, SQLITE_ANY, 0, create_vector, 0, 0)
) {
*err=sqlite3_mprintf("Error registering create_vector: %s",
sqlite3_errmsg(db));
return ret;
}

// Register the display_vector function
if( int ret = sqlite3_create_function(
db, "display_vector", 1, SQLITE_ANY, 0, display_vector, 0, 0)
) {
*err=sqlite3_mprintf("Error registering display_vector: %s",
sqlite3_errmsg(db));
return ret;
}

// If we've made it this far, we should be ok
return SQLITE_OK;
}

我们可以这样编译:

$ make
g++ -g -std=c++14 blob.cpp -shared -o blob.so -fPIC

现在,如果我们像宣传的那样使用这些函数,一切正常:

sqlite> .load "./blob.so"
sqlite> select display_vector(create_vector());
[ 1.200000, 3.400000, 5.600000, 7.800000, 9.100000 ]

但是,如果我们尝试在非 vector 上使用 display_vector,我们会出现段错误:

sqlite> .load "./blob.so"
sqlite> select display_vector(NULL);
Segmentation fault

实际上,问题在于 display_vector vector 中的 static_cast 不正确。无论如何,有没有一种检查 blob 类型甚至保证我们有 blob 的好方法?当新扩展需要特定类型的输入时,是否有防止段错误的好方法?

最佳答案

一个 blob 只是一堆字节,并不是每个值都是一个 blob。

您的函数应使用 sqlite3_value_type() 检查值的类型, 并使用 sqlite3_value_bytes() 检查长度.

关于c++ - 在 SQLite 中使用 blob 时如何处理类型错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31125989/

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