Sqlite3和pthread,双自由或损坏(out)

Sqlite3 and pthread, double free or corruption (out)

本文关键字:损坏 out 自由 pthread Sqlite3      更新时间:2023-10-16

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

双倍空闲或损坏(出) 中止(转储核心)

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

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

有人知道是什么导致了异常吗?这是我的代码:链接

数据库类:

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: %sn", sqlite3_errmsg(db));
exit(1);
}
else
{
fprintf(stderr, "Opened database successfullyn");
}
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)。


编辑后:

现在data是从Select返回的,从未写入,但随后在中被取消引用

returnData[0]

在CCD_ 14中。这是不明确的行为。

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

则指针argv[i - index]也可以是NULL以指示返回行中的NULL值(参见sqlite3_exec的文档)。在这种情况下,来自它的strcpy也将是未定义的行为。

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


您也有内存泄漏,因为您从未free任何malloced数据,并且因为dataToReturn在每次回调调用结束时都会被丢弃,所以它不是很有用。


没有充分的理由使用所有这些C样式构造。使用new代替mallocstd::stringstd::vector代替char阵列,std::coutstd::cerr代替printffprintf(stcerr, ...std::thread代替pthreads。唯一需要考虑的是C库的接口边界。