Segfault when trying to use std::vector in mex function

Hello all,
I am having a bit of a hard time resolving this issue. I thought that stl containers were supported in matlab, so maybe I'm doing something wrong.
The problem I have is the following:
I first retrieve the (single-precision) data as
float * someData = (float *)mxGetData(prhs[0]);
//the size below is in terms of number of components
int someDataSize = std::floor( *(float *) mxGetData(prhs[1]));
then I try to populate a vector which I initialize as
struct ThreadData {
std::vector<float> someDataVec;
}
with
someDataVec.insert(someDataVec.end(), someData, someData + someDataSize);
So to be clear: if someData is an array of 600 floats then someDataSize = 600. However, the insert (I have multiple such inserts) throws a seg-fault complaining specifically about "memmove" in "libc.so.6".
I'm currently using gcc.4.3.6, but I've also tried gcc.4.8.2 with Matlab 2014a on Red Hat. The issue persists on both compilers.
I have also tried to insert with
std::copy( someData, someData + someDataSize,
std::back_inserter(someDataVec));
and using
someDataVec.resize(someDataSize);
someDataVec.assign(someData, someData + someDataSize);
but to no avail. The exception is always the same. (Note that I have read threads making reference to a compiler flag "SECURE_SCL=0", however, I have checked mexopts.sh and this flag does not exist.) The same approach with c-style pointers (ie, float*) works without any issues.
Looking forward to your insight.
Cheers, Alvin
=============================================================================
Edit: The initialization of the structure containing the vector was incorrect. The structure is allocated in C-style (ie, using malloc as opposed to new). Resizing the vector results in an (obvious) segmentation violation.
Problem:
ThreadData * data = (ThreadData *)malloc(sizeof(ThreadData) * NUM_THREADS);
for(int i=1; i< NUM_THREADS; i++) {
data[i].someDataVec.insert( data[i].someDataVec.end(), someData, someData + someDataSize);
}
Solution:
ThreadData * data = new ThreadData[NUM_THREADS];
for(int i=1; i< NUM_THREADS; i++) {
data[i].someDataVec.insert( data[i].someDataVec.end(), someData, someData + someDataSize);
}
It is an oversight that has cost me much time.
For reference: I used electric fence to find the true violation. previous to using efence a few insertions would succeed before randomly segfaulting.

Answers (1)

Your post suffers from the fact that you show only partial code snippets of lines, making it impossible for the reader to know exactly what you are doing behind the (...). Based on what you have posted, I would look at this line:
int someDataSize = std::floor( *(float *) mxGetData(...));
Why would someDataSize be a function of the values in the array? Doesn't make sense to me. I would have expected something like this instead:
mwSize someDataSize = mxGetNumberOfElements(...);

3 Comments

Hi James,
The code around this is massive so I've shaved it down to the things causing the problem, but I understand your concern, so let me make some things clearer.
(1) The line you've posted is first of all not the problem because I've been debugging this with gdb for days and have gone over each variable and value in detail. They are all correct.
(2) The lines with the ellipsis are specifically:
float * someData = (float *) mxGetData( prhs[0] );
int someDataSize = std::floor( * (float *) mxGetData( prhs[1] ) );
// both of the above you can assume are correct
std::vector<float> someDataVec;
// the next statement is the problem (SIGSEGV)
someDataVec.insert(someDataVec.end(), someData, someData + someDataSize);
To be clearer, "someDataSize" is passed as a parameter because it is smaller than the size of "someData"; the latter is much larger.
If I run even this code on my machine inside a mex function it will generate a segmentation fault.
Can you put in a check to make me feel better?
if( someDataSize > mxGetNumberOfElements(prhs[0]) ) {
mexErrMsgTxt("2nd argument is greater than size of 1st argument");
}
if( !mxIsSingle(prhs[0]) ) {
mexErrMsgTxt("1st argument is not single class");
}
I unintentionally lied to you... See the edit above. I oversimplified the code I showed you. In fact in the test I carried the malloc'd struct array without paying attention. Apologies for this...
BUT I will put your suggested check in the code.
Thanks for the help.

Sign in to comment.

Categories

Asked:

on 17 Mar 2015

Edited:

on 18 Mar 2015

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!