Note that there are some explanatory texts on larger screens.

plurals
  1. POMySQL/C++ - Segmentation Fault after calling ResultSet->next()
    primarykey
    data
    text
    <p>I'm getting a lot of problems while trying to implement a <strong>MySQL</strong> query on a <strong>multithreaded</strong> c++ application. My main problem comes when I call the <code>next()</code> method from the <code>ResultSet</code> after the query to the DB has been done (correctly), since it produces a <strong>segmentation fault</strong> and the next output from Valgrind:</p> <pre><code>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) </code></pre> <hr> <p>I'm almost sure that the problem comes from the fact that I reserve the <strong>local memory</strong> for every thread using an <strong>"array of structs"</strong> like this:</p> <pre><code>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); </code></pre> <hr> <p>I tried things like reserving space for <code>result</code> manually with <code>memset</code>, declaring it locally from every thread, reserving even more space for <code>tinfo</code> but unfortunately nothing worked.</p> <h2>Summary:</h2> <p>I basically think I need a way to reserve enough space for <code>result</code> before I call: <code>private_tms-&gt;result = private_tms-&gt;stmt-&gt;executeQuery("SELECT * FROM DB WHERE id='1' ");</code> from every thread , because is probably overwriting some random memory addresses and thus provoking the <strong>SEGFAULT</strong> after trying to access them with <code>next()</code>.</p> <p>I really hope that someone may give me a useful idea before I see myself forced to start the implementation from scratch with the old <strong>C-API</strong> for the purpose of being able to "touch the memory" more directly. </p> <p>Thanks in advance and I'm sorry if I did not express properly mi ideas.</p> <p><strong>Edit:</strong> MYSQL query snippet: <a href="https://gist.github.com/srt199/6216375" rel="nofollow">link</a></p> <hr> <h2>Further research:</h2> <p>After some investigation I found the next things:</p> <ol> <li><code>private_tms-&gt;result</code> points to the address <code>0xe0000000</code> (<strong>the same that valgrind names as the one that can not be accessed!</strong>)</li> <li><code>(private_tms-&gt;result)-&gt;next()</code> points to the address <code>0xe0000090</code> (also regarded as inaccessible by gdb)</li> <li>The output of the command <code>pmap</code> doesn't list any of these addresses.</li> </ol> <p><strong>My conclusion:</strong> I think that the problem may be in the address where the data generated by <code>executeQuery()</code> is placed, as it may be colliding with previously allocated data or simply using inaccessible/undeclared/restricted addresses, but because of my inexperience I am unable to find a proper solution by now. </p> <p>Some of the possible solutions (probably naive) that come to my head are: </p> <ol> <li>Controlling the address where <code>executeQuery()</code> places the data. </li> <li>Using a <code>sql::ResultSet</code> (<strong>not a pointer</strong>) declared locally for every thread to get the result of <code>executeQuery()</code>, thus avoiding problems related with "random" memory allocation . (though I think this is not possible given the API specifications). </li> </ol>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. COAs far as C++ is concerned, don't use (raw) pointers or C-style casts. These just make it easier to make mistakes. Concerning the DB access, what makes you so sure that the call to next() doesn't change things under the hood that might be shared between threads? You'll need completely separate instances to assure that and looking at your code I question that you have those. Talking about code, it would help seeing a minimal example, exactly because there's too much C++ and/or SQL that could go wrong.
      singulars
    2. COI already tried to change some of my C-style code, but one of the most problematic parts was the reservation of space for the array of structs with the exact number of bytes, so after a bunch of SEGFAULTS I decided to surrender...
      singulars
    3. CORegarding to the call to next() I think is very important what you said about the things it may be changing silently. I found this explanation in the documentation: _A ResultSet maintains a cursor pointing to its current row of data. Initially the cursor is positioned before the first row. The next method moves the cursor to the next row._ That made me think even more about how could I reserve the needed memory for the ResultSet.
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload