gpt4 book ai didi

c - 在sqlite的回调函数中动态重新分配2个dim数组

转载 作者:太空宇宙 更新时间:2023-11-04 04:27:29 27 4
gpt4 key购买 nike

我正在为教育目的开发 sqlite-.dll。每次使用数据库中的新行调用回调函数时,我都试图在我的二维数组中动态添加一行。 (例如从客户中选择 *)。然后应将存储在此数组中的数据作为 C 接口(interface)返回。

SQLCONTROL_API char** sql_execQuery(char *dbName, char *sqlStatement)
{
char **a = 0;
/*Some sqlite stuff*/
int rc = sqlite3_exec(db, sqlStatement, callback, &a, &zErrMsg);
return a;
}

回调函数:

static int callback(void *data, int argc, char **argv, char **azColName)
{
char **old = (char **)data;
int num_rows = sizeof(old) / sizeof(old[0]);
int num_cols = sizeof(old[0]) / sizeof(old[0][0]);

old = (char **)realloc(old, (num_rows + 1) * sizeof(char *));
for (int i = 0; i < (num_rows + 1); i++)
old[i] = (char *)realloc(old[i], argc * sizeof(char *));

/*I am trying to create a 2 dim array that looks like a table,
so the column names are in the first row,
then the data from the table is stored in each row*/
for (int i = 0; i < argc; i++)
{
if (num_rows == 1)
old[0][i] = *azColName[i];

old[num_rows][i] = *argv[i];
}
data = old;
return 0;
}

向数据库中插入数据时,一切正常。但是当我尝试检索数据时,我遇到了读取访问冲突。现在我的问题是,我的方法是否正确,或者我是否错过了一些重要的意图要求?

最佳答案

在您的 sql_execQuery() 中,您将 a 声明为 char **,并传递其地址&a,作为sqlite3_exec()的第四个参数。因此,该参数的类型为 char ***,并且它指向程序堆栈中某处的位置。这本身并没有错。

但随后我们到达了 callback(),它有严重的问题,其中主要问题:

  • 它将data 指针视为char ** 类型,而不是正确的char *** 类型。如果那是你唯一的问题,你可以这样解决:
char **old = *(char ***)data;

// ...

*(char ***)data = old;
  • 它尝试通过 sizeof 运算符计算分配空间的维度,如果 old 实际上是一个二维数组,这将是合理的,但是它根本不是一个数组。它是指向 char 的指针,所以 sizeof(old) 是指针的大小(指向 char 的指针),sizeof(old[0]) 是指针的大小(指向 char),sizeof(old[0][0]) 是大小一个 char。这不会告诉您有关已分配多少空间的任何信息。

  • 在为 old 分配内存后,它取消引用分配内存的部分而不对其进行初始化,方法是将它们传递给 realloc()。通常,除其中之一外,所有这些都已初始化,但未初始化的会导致 realloc() 表现出未定义的行为。

  • 您未能检查分配错误。

看起来您需要将更复杂的数据结构传递给您的回调,以便您可以跟踪分配的维度。像这样的东西,例如:

struct mytable {
char **data;
size_t dim;
};

SQLCONTROL_API char** sql_execQuery(char *dbName, char *sqlStatement)
{
struct mytable a = { NULL, 0 };

// ...

int rc = sqlite3_exec(db, sqlStatement, callback, &a, &zErrMsg);

return a.data;
}

static int callback(void *data, int argc, char **argv, char **azColName)
{
struct mytable *old = data;
char **temp;

old->dim++;
temp = realloc(old->data, old->dim * sizeof(*old->data));
if (temp) {
old->data = temp;
old->data[old->dim - 1] = NULL;
} else {
// handle allocation error ...
}

for (int i = 0; i < old->dim; i++) {
char *temp2 = realloc(old->data[i], argc * sizeof(*old->data[i]));

if (temp2) {
old->data[i] = temp2;
old->data[i][argc - 1] = NULL;
} else {
// handle allocation error ...
}
}

// ... other stuff ...

// no need for anything like data = old

return 0;
}

关于c - 在sqlite的回调函数中动态重新分配2个dim数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40096266/

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