gpt4 book ai didi

c++ - Sqlite3 和 pthread,双重释放或损坏(出)

转载 作者:太空宇宙 更新时间:2023-11-04 05:41:33 26 4
gpt4 key购买 nike

我尝试创建一个连接到数据库的线程,从那里获取一些数据并打印到控制台。问题是当该线程完成时抛出异常:

双重免费或腐败(出局)中止(核心转储)

我尝试使用 sqlite3 和 pthread,但这两个并不是真正的 friend 。

我想,但我不确定问题是否来自数据库类。

有人知道是什么产生了异常吗?这是我的代码:link

数据库类:

class Database {
private:
sqlite3 *db;
static int CallBack(void *data, int argc, char **argv, char **azColName)
{
int index = 0;
char** dataToReturn = new char*[1000];

while (dataToReturn[index])
{
index++;
}

for (int i = index; i < argc + index; i++)
{
dataToReturn[i] = (char *)malloc(sizeof(char) * sizeof(argv[i - index]));
strcpy((dataToReturn)[i], argv[i - index]);
}

return 0;
}

public:
char **Select()
{
char *zErrMsg = 0;
int rc;

rc = sqlite3_open("test.db", &db);

if (rc)
{
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
exit(1);
}
else
{
fprintf(stderr, "Opened database successfully\n");
}
char **data;

int rc2 = sqlite3_exec(db, "SELECT * FROM SHARED_FILE", CallBack, data, &zErrMsg);

if (rc2 != SQLITE_OK)
{
sqlite3_free(zErrMsg);
exit(2);
}

sqlite3_close(db);
return data;
}

线程函数:

static void FunctioForThread()
{
printf("start");

auto database = new Database();
char** returnData = database->Select();

printf("something from db: %s \n", returnData[0]);
printf("stop");
}

static void *threadd(void *arg)
{
pthread_detach(pthread_self());
fflush(stdout);

FunctioForThread();
}

主要功能:

int main()
{
pthread_t thread;
char arg[100] = "test";
pthread_create(&thread, NULL, &threadd, arg);

while(1);
}

最佳答案

您正在取消引用((char **)data)[index]中传递给CallBackdata,但其值是通过sqlite3_exec的回调从Select中的data传递的。 Select 中的 data 已分配给以下位置:

char **data = (char **)malloc(0);

不允许取消引用零长度分配的指针。另请注意,零大小 malloc 的行为是实现定义的,因此应该避免它(就像 C++ 中的 malloc 无论如何都优先于 new 一样)。

<小时/>

编辑后:

现在 dataSelect 返回,但从未写入它,但随后在

中取消引用
returnData[0]

FunctioForThread中。这是未定义的行为。

此外,sizeof(argv[i - index]) 不会返回 argv[i - index] 指向的字符串的长度。它将返回指针类型的大小。因此,您的分配可能会太小,这又是未定义的行为。使用 std::strlen 获取以零结尾的字符串的长度。

那么指针argv[i - index]也可能是NULL以指示返回行中的NULL值(参见documentation of sqlite3_exec)。在这种情况下,从中进行 strcpy 操作也将是未定义的行为。

循环while (dataToReturn[index])将导致未定义的行为,因为dataToReturn的数组已分配,但其元素从未设置。即使设置了值,请注意,当且仅当 C 样式字符串 dataToReturn[index] 指向的长度为零时,才满足条件。如果分配的范围内不存在这样的字符串,则该行为再次未定义。

<小时/>

您还存在内存泄漏,因为您从未释放任何malloc的数据,并且因为dataToReturn在每次CallBack调用结束时被丢弃,所以它不是很有用。

<小时/>

没有充分的理由使用所有这些 C 风格的构造。使用 new 代替 malloc,使用 std::stringstd::vector 代替 char 数组,使用 std::coutstd::cerr 代替 printffprintf(stcerr, ...std::thread 代替 pthreads。唯一需要考虑的一点是 C 库的接口(interface)边界。

关于c++ - Sqlite3 和 pthread,双重释放或损坏(出),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53964158/

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