I try to create a thread which connect to a database, takes some data from there and print to the console. The problem is that when that thread finish throw an exception:
double free or corruption (out) Aborted (core dumped)
I try to use sqlite3 and pthread and this two are not really friends.
I think, but I am not sure that the problems comes from the Database class.
Anyone have any idea what produce the exception? Here is my code: link
Database class:
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;
}
Thread functions:
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();
}
And the main function:
int main()
{
pthread_t thread;
char arg[100] = "test";
pthread_create(&thread, NULL, &threadd, arg);
while(1);
}
You are dereferencing data
passed to CallBack
in ((char **)data)[index]
, but its value was passed from data
in Select
through the callback of sqlite3_exec
. data
in Select
was allocated for in:
char **data = (char **)malloc(0);
You are not allowed to dereference a pointer to a zero-length allocation. Also note that the behavior of a zero-size malloc
is implementation-defined, so it should be avoided (as should malloc
in C++ in preference of new
anyway).
After edit:
Now data
is returned from Select
without ever writing to it, but is then dereferenced in
returnData[0]
in FunctioForThread
. That is undefined behaior.
Furthermore sizeof(argv[i - index])
does not return the length of the string that argv[i - index]
points to. It will return the size of the pointer type. Probably your allocations will therefore be too small, again undefined behavior. Use std::strlen
to get the length of a zero-terminated string.
Then the pointer argv[i - index]
may also be NULL
to indicate a NULL
value in the returned row (see documentation of sqlite3_exec
). In that case strcpy
ing from it will also be undefined behavior.
The loop while (dataToReturn[index])
will cause undefined behavior because an array for dataToReturn
was allocated, but its elements never set. Even if the values were set, note that the condition is satisfied if and only if the C-style string dataToReturn[index]
points to has length zero. If such a string doesn't exist in the allocated range, again the behavior is undefined.
You also have memory leaks because you never free
any of your malloc
ed data and because dataToReturn
is discarded at the end of each CallBack call, it is not very useful.
There is no good reason to use all these C-style constructs. Use new
instead of malloc
, std::string
and std::vector
instead of char
arrays, std::cout
and std::cerr
instead of printf
and fprintf(stcerr, ...
, std::thread
instead of pthreads
. The only point were these things need to be considered is at the interface boundary to the C library.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.