我尝试创建一个连接数据库的线程,从那里获取一些数据并打印到控制台。问题在于,当该线程完成时会引发异常:
双重释放或腐败(淘汰) 已中止(核心已弃用)
我尝试使用sqlite3和pthread,但这两个并不是真正的朋友。
我认为,但是我不确定问题是否来自数据库类。
任何人都知道产生异常的原因是什么? 这是我的代码: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);
}
答案 0 :(得分:1)
您要取消引用data
中传递给CallBack
的{{1}},但其值是通过{{1}的回调从((char **)data)[index]
中的data
传递的}。 Select
中的sqlite3_exec
已分配给:
data
不允许您取消引用指向零长度分配的指针。还要注意,零尺寸Select
的行为是实现定义的,因此应避免使用(就像C ++中的char **data = (char **)malloc(0);
应该优先于malloc
一样)。
编辑后:
现在malloc
从new
返回,而从未写入,但随后在其中取消引用
data
在Select
中。那是不确定的。
此外,returnData[0]
不返回FunctioForThread
指向的字符串的长度。它将返回指针类型的大小。因此,您的分配可能会太小,再次是未定义的行为。使用sizeof(argv[i - index])
获取以零结尾的字符串的长度。
然后,指针argv[i - index]
也可以是std::strlen
,以指示返回行中的argv[i - index]
值(请参见documentation of sqlite3_exec
)。在这种情况下,NULL
的行为也将是未定义的行为。
循环NULL
将导致未定义的行为,因为已分配了strcpy
的数组,但从未设置其元素。
即使设置了值,也请注意,并且仅当C样式字符串while (dataToReturn[index])
指向长度为零时,该条件才得到满足。如果在分配的范围内不存在这样的字符串,则行为将再次不确定。
您还存在内存泄漏,因为您从未dataToReturn
编辑过任何数据dataToReturn[index]
,并且由于free
在每个CallBack调用结束时被丢弃,因此它不是很有用。 / p>
没有充分的理由使用所有这些C样式的构造。使用malloc
代替dataToReturn
,new
和malloc
代替std::string
数组,使用std::vector
和char
代替{{1 }}和std::cout
,而不是std::cerr
,printf
。唯一需要考虑的事情就是C库的接口边界。