Nkr Nkr - 1 month ago 8
C++ Question

C++ Threading with multidimensional vectors - access violation

first of all sorry for my bad english, Im no native speaker and this is my first post. Im currently trying to get work done in a threaded member function of my class. Therefore it gets a 2d array as parameter and fills it in the member function. This gets repeated multiple times. Right after spawning the first thread I get an error with either read or write access violation. I tried different approches to solve it, but cant get it to work. While I found nearly any problem already solved here, in this case I was unsuccessfull finding something for quite a while now.

void myClass::process(Vector3D& out_stack, long filterFaktor){
long rowSize = this->input2D.size();
long colSize = this->input2D.at(0).size();
int filterPerRowCount = ceil((double)rowSize / filterFaktor);
int filterPerColCount = ceil((double)colSize / filterFaktor);

std::vector<std::thread> threadPool;
//create new filter
long currentrow = 0;
while (currentrow < rowSize) {
long currentcol = 0;
while (currentcol < colSize) {
Filter* nextFilter = &this->createNextFilter(currentrow, currentcol, filterPerRowCount, filterPerColCount);
out_stack.push_back(Vector2D());
Vector2D* nptr = &out_stack[out_stack.size()-1];

//Here we are calling the thread which leads to the access violation
threadPool.push_back(std::thread(&myClass::nextProcess, this, nextFilter, nptr, rowSize, colSize));

currentcol += filterPerColCount;
}
currentrow += filterPerRowCount;
}
//wait until threads have finished
for (int iThread = 0; iThread < threadPool.size(); iThread++) {
threadPool[iThread].join();
}
}

void myClass::nextProcess(Filter* nextfilter, Vector2D* out_Map, long rowCount, long colCount){
//Loops this part -> creates the rows and pushes them in the out_Map
std::vector<double> nextRowInMap;
//... Calculates sum
nextRowInMap.push_back(sum);

//Push row in vector -> This is where the error occurs
out_Map->push_back(nextRowInMap);
}



typedef std::vector<double> Vector1D;
typedef std::vector<Vector1D> Vector2D;
typedef std::vector<Vector2D> Vector3D;


I think im just missing knowledge in using Pointers in C++, cause im new to it.

Thanks in advance & best regards

EDIT

Tried it now this way, still dont work:

out_stack.push_back(Vector2D());
long index = out_stack.size() - 1;
threadPool.push_back(std::thread(&myClass::nextProcess, this, nextFilter, &out_stack, index, rowSize, colSize));


And in nextProcess:

out_stack->at(index).push_back(nextRowInMap);


EDIT
Solved with mutex. Additionally I needed to pass the filter not on reference.

Answer

You error is here:

out_stack.push_back(Vector2D());
Vector2D* nptr = &out_stack[out_stack.size()-1];

There is no guarantee that the object stays at the same address when you modify the vector. When the vector has to grow it can allocate the internal memory on another address and move the objects in the vector to a new address. So the pointer can get invalid on the next push_back

You should pass the vector and index to the thread and access it each time you need it

out_stack[index].push_back(...)

It may be that after out_stack[index] and before push_back the vector gets modified and you are also operating on invalid memory. So you should protect accessing/modifying the vector with a std::mutex. I am not sure on that last part though if there is some thread safety guarantee there I don't know of.

Comments