Segfault when trying to use std::vector in mex function
1 view (last 30 days)
Show older comments
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.
0 Comments
Answers (1)
James Tursa
on 17 Mar 2015
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
James Tursa
on 17 Mar 2015
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");
}
See Also
Categories
Find more on MATLAB Compiler in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!