我在尝试在多线程 c ++应用程序上实现 MySQL 查询时遇到了很多问题。我的主要问题是在查询到DB(正确)后,从next()
调用ResultSet
方法,因为它产生分段错误,然后是下一个Valgrind的输出:
Invalid read of size 4
==24124== at 0x80557EF: sql_query(thread_info*) (SVMread.cpp:44)
==24124== by 0x805764B: SVM_query(void*, cv::Mat*, cv::Mat*) (SVMread.cpp:358)
==24124== by 0x8053803: thread_main(void*) (threads.cpp:543)
==24124== by 0x4373D4B: start_thread (pthread_create.c:308)
==24124== by 0x4C88DDD: clone (clone.S:130)
==24124== Address 0xe0000090 is not stack'd, malloc'd or (recently) free'd
==24124==
==24124==
==24124== Process terminating with default action of signal 11 (SIGSEGV)
==24124== Access not within mapped region at address 0xE0000090
==24124== at 0x80557EF: sql_query(thread_info*) (SVMread.cpp:44)
==24124== by 0x805764B: SVM_query(void*, cv::Mat*, cv::Mat*) (SVMread.cpp:358)
==24124== by 0x8053803: thread_main(void*) (threads.cpp:543)
==24124== by 0x4373D4B: start_thread (pthread_create.c:308)
==24124== by 0x4C88DDD: clone (clone.S:130)
我几乎可以肯定,问题来自于我为每个线程使用“结构数组保留本地内存这样的事实:
struct thread_info {
sql::Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *result;
// ......
}
// declare array of structs with enough space:
tinfo = (thread_info * ) calloc(nthreads, sizeof(thread_info)+100000);
我尝试使用result
手动为memset
预留空间,从每个线程在本地声明它,为tinfo
保留更多空间,但遗憾的是没有任何效果。
我基本上认为在从每个线程调用result
之前我需要一种为private_tms->result = private_tms->stmt->executeQuery("SELECT * FROM DB WHERE id='1' ");
保留足够空间的方法,因为它可能会覆盖一些随机内存地址,从而激发 SEGFAULT < / strong>尝试使用next()
访问它们时。
我真的希望有人可能会给我一个有用的想法,然后才能看到自己被迫从头开始使用旧的 C-API 来实现“触摸内存”的目的更直接。
提前致谢,如果我没有表达正确的想法,我很抱歉。
修改 MYSQL查询摘要:link
经过一番调查后,我发现了接下来的事情:
private_tms->result
指向地址0xe0000000
(与valgrind名称相同,无法访问的地址!)(private_tms->result)->next()
指向地址0xe0000090
(也被gdb视为无法访问)pmap
的输出未列出任何这些地址。 我的结论:我认为问题可能出在executeQuery()
生成的数据的地址中,因为它可能与以前分配的数据发生冲突,或者只是使用不可访问的/未申报/限制地址,但由于我的经验不足,我现在无法找到适当的解决方案。
我想到的一些可能的解决方案(可能是天真的)是:
executeQuery()
放置数据的地址。 sql::ResultSet
(非指针)来获取executeQuery()
的结果,从而避免与“随机”内存分配相关的问题。 (虽然我认为根据API规范这是不可能的)。