0

I build a multithreaded system with OpenCV, which creates some images, assigns them into a vector and sends each image into a different thread.

This is how it looks like:

std::vector<cv::Mat> images;
for (int i = 0 ; i < 10 ; i++) {
    images.push_back(cv::Mat(/* bla bla */));
    cv::Mat& mat = images.back();
    std::thread(some_function_name, &mat)
}
// Wait here for all threads to join (didn't show its code)

It seems that when the thread gets the pointer to the Mat object, the Mat object doesn't anymore exist. Is it possible that although it was immediately assigned to the vector, it was actually destroyed when the loop ended, as it was wiped off the stack?

SomethingSomething
  • 11,491
  • 17
  • 68
  • 126

1 Answers1

2

Your problem is actually the fact that you are calling push_back in the loop, which may cause reallocations. If that occurs, the underlying data will be copied, so any pointers or references will be invalidated.

To resolve this, one way would be to size the array ahead of time

std::vector<cv::Mat> images(10);
for (int i = 0 ; i < 10 ; i++) {
    images[i] = cv::Mat(/* bla bla */);
    cv::Mat& mat = images.at(i);
    std::thread(some_function_name, &mat)
}
// Wait here for all threads to join (didn't show its code)
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • Do you actually say that the `vector`'s self-extension operations that occur from time to time cause it? So if I use `std::list` instead, would it be prevented? – SomethingSomething May 10 '17 at 07:45
  • 1
    @SomethingSomething [Read this post](https://stackoverflow.com/questions/17299951/c-vector-what-happens-whenever-it-expands-reallocate-on-stack) that explains what happens "under the hood" when you add elements to a `std::vector`. Yes you could use a `std::list` to avoid this, but that would just be avoiding the problem, it is better to understand *why* this is occurring in the first place, so you understand the behavior of the different standard library containers. – Cory Kramer May 10 '17 at 11:26
  • Fine, I understand, I learned in "Data Structures" course that using Amortized Analysis, if you extend the vector each time its size is (2^i), then your average complexity is O(1) - and I understand it's done in C++ using "realloc()" - I just didn't think that deeply when I wrote my code. I asked the question in the last comment just to make sure you meant to that specific realloc – SomethingSomething May 10 '17 at 12:11
  • Thank you very much, both for your very helpful answer and for answering my question in the comment! – SomethingSomething May 10 '17 at 12:16