Reputation: 4805
I have a program that is using opencv. The opencv part does nothing fancy, it just receives images from a webcam, finds some markers in it and estimates their poses. However, I reliably get the error
OpenCV Error: Insufficient memory (Failed to allocate 9892156749154358672 bytes) in OutOfMemoryError, file /home/XYZ/opencv/modules/core/src/alloc.cpp, line 52
That is almost 10 exabyte, I highly doubt that I am doing anything at this magnitude, even if it runs out of memory and tries to double it with reallocation. I also noticed:
I had the same error previously, but it inexplainably dissappeared after I commented 3 lines of code which where basically (in the code of the program that does NOT depend on opencv):
std::cout << "This is an int: " << something->getInt() << std::endl;
So not related to opencv in the slightest. Because this happended, and the error dissappeared after commenting these lines, I am really confused as of what causes this now. I feel like any line of my code might be the reason, but I can't identify it. This why can not provide you with a minimal example to reproduce this. I will now show you the piece of code that actually does something with opencv; I removed the parts that do the marker tracking, assume everything here is defined:
int PoseEstimator::trackMarkers(bool estimatePose, int camId, string camParams)
{
cv::VideoCapture inputVideo;
int waitTime = 10;
inputVideo.open(camId);
cv::Mat inputImage, inputImageCopy;
inputVideo >> inputImage;
iThreshParam1 = markerDetector.getParams()._thresParam1;
iThreshParam2 = markerDetector.getParams()._thresParam2;
cv::namedWindow("threshold");
cv::createTrackbar("ThresParam1", "threshold", &iThreshParam1, 25, callTrackBarCallback, (void*) &iThreshParam1);
cv::createTrackbar("ThresParam2", "threshold", &iThreshParam2, 13, callTrackBarCallback, (void*) &iThreshParam2);
do {
inputVideo.retrieve(inputImage);
//This is 620x480, not gigantic
inputImage.copyTo(inputImageCopy);
for(unsigned int i = 0; i < markers.size(); i++)
{
//Code to track the markers with arucuo library
cv::Mat transformMatrix = markerTracker[id].getRTMatrix();
//This is only a 4x4 matrix
}
cv::imshow("input", inputImageCopy);
cv::imshow("threshold", markerDetector.getThresholdedImage());
inputImageCopy.release();
inputImage.release();
key = cv::waitKey(waitTime);
if(key == 's')
waitTime = waitTime == 0 ? 10:0;
} while (key != 27 && (inputVideo.grab()));
return 0;
}
I believe that whole loop should allocate roughly 2*620*480+4*4*markerCount bit per interation, and that memory is released on every new iteration. I don't believe this can be the cause, but has anyone else got a clue or experienced this before?
Thanks for any hints! I'll gladly provide you with more details if needed.
Edit: The closest I've been able to come to narrow this down: I am running something using boost::async.
This is the code that gets executed right before the error happens:
bool MarkerTracker::doSomething()
{
boost::unique_future<bool> future = boost::async(boost::launch::async,[this]()
{
bool planAgain = true;
bool success;
int c = 0;
int planLimit = 1;
double totalPlanningTime = 0.0;
auto startTotal = std::chrono::system_clock::now();
while(planAgain && c < planLimit && (printf("DEBUG loop\n") || true))
{
TrajectoryPlanner planner = TrajectoryPlanner(GetEnv());
std::cout << "planning now " << std::endl;
auto start = std::chrono::system_clock::now();
success = planner.plan();
std::chrono::duration<double> diff = std::chrono::system_clock::now() - start;
totalPlanningTime += diff.count();
if(success)
{
planAgain = !robotController->receiveFoundPath(planner.getLastSuccessfullPath());
std::cout << "DEBUG sent Path" << std::endl;
} else
{
planAgain = false;
}
c++;
}
std::cout << "DEBUG final steps" << std::endl;
std::chrono::duration<double> diffTotal = std::chrono::system_clock::now() - startTotal;
std::cout << "DEBUG got time" << std::endl;
std::cout << std::endl << std::endl << "Planned " << c << " times." << std::endl << std::endl ;
return success && !planAgain;
}
});
return future.get();
}
So what gets printed in the end? "DEBUG sent Path" is the last thing I see. I believe the next step in the code would be the evaluation of the loop condition (Edit: The increment in the end is executed without problems). However, the "DEBUG loop" statement is not printed (maybe the compiler optimizes that away? But it shouldn't because it can't know that printf wont have any side effects). I highly doubt that comparing an int and a bool cause the allocation of 10 exabyte. This statement should evaluate to false anyways, so "DEBUG final steps" should be printed, which it is not.
Upvotes: 1
Views: 151
Reputation: 4805
Pointers are not initialized to 0 automatically in C++. The destructor of the TrajectoryPlanner object had something like
DebugDrawer *debugDrawer;
TrajectoryPlanner::~TrajectoryPlanner()
{
if(debugDrawer)
{
delete debugDrawer;
}
}
However, the pointer was never initialized, thus the pointer was set to random bytes in memory. Since C++ evaluates non-zero ints to true, the delete call was made. (See Why aren't pointers initialized with NULL by default?)
This caused a release call to a cv::Mat inside the DebugDrawer destructor, which is from another library, so I didn't need to link again OpenCV to use it. Apparently trying to release memory that is not owned in the first place causes this allocation request.
Upvotes: 1