MySQL / C ++ - 调用ResultSet后的分段错误 - > next()

时间:2013-08-12 12:53:38

标签: c++ mysql multithreading memory-management

我在尝试在多线程 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


进一步研究:

经过一番调查后,我发现了接下来的事情:

  1. private_tms->result指向地址0xe0000000与valgrind名称相同,无法访问的地址!
  2. (private_tms->result)->next()指向地址0xe0000090(也被gdb视为无法访问)
  3. 命令pmap的输出未列出任何这些地址。
  4. 我的结论:我认为问题可能出在executeQuery()生成的数据的地址中,因为它可能与以前分配的数据发生冲突,或者只是使用不可访问的/未申报/限制地址,但由于我的经验不足,我现在无法找到适当的解决方案。

    我想到的一些可能的解决方案(可能是天真的)是:

    1. 控制executeQuery()放置数据的地址。
    2. 使用本地为每个线程声明的sql::ResultSet非指针)来获取executeQuery()的结果,从而避免与“随机”内存分配相关的问题。 (虽然我认为根据API规范这是不可能的)。

0 个答案:

没有答案