QQueue and Segmentation fault
-
Dear All,
I use QQueue and when I tried to dequeue, I always get segmentation fault.
What could be the reason.
My dequeue code is very simple as follow.
@IplImage ImageQueue::getQueue()
{
IplImage ret;
lockforImageRecord.lock();
if(ImageQueue::imageRecord.count()>0)
ret = ImageQueue::imageRecord.dequeue();
lockforImageRecord.unlock();
return ret;
}@ -
For debugging:
First of all: comment out the 2 lock lines.
Put a break point, and try to step through your code.
That will shows you what the problem can be.
Maybe your imageRecord is null(?). Or you get back a null reference with the return statement. Segmentation fault is always a memory address problem (pointer to nothing...).
(If your code is running well, comment back your 2 lock lines, because probably you have problem with locking). -
Maybe in your case it is a problem of returning object that is allocated on stack and when you exit from function this object is removed and you are trying to return it and use in other function.
@
IplImage ret;
...
return ret;
@Is it safe to return this object (any copy constructor)?
-
You are allowed to return local objects by value, but not by reference or pointer.
-
Thanks for all. Now I found the problem.
I made the queue as static in the class.
Then I am accessing the static queue from the instance of the class.
Now I changed my methods to static as well and access by class itself. Now fine.
Thanks -
I have one more question though.
I make an instance of IplImage.IplImage* opencvimageframe;
//get new instance
opencvimageframe = cvCreateImage(cvSize(col, row), IPL_DEPTH_8U, 1);
//then put the object, not the instance, into the Queue.
ImageQueue::setQueue(*opencvimageframe);I have to release the opencvimageframe using
cvReleaseImage( &opencvimageframe );
Where should I release , can I release straightaway after setting into the queue? My queue setting method is
void ImageQueue::setQueue(const IplImage& imageIn)
{
int i;
lockforImageRecord.lock();
ImageQueue::imageRecord.enqueue(imageIn);
lockforImageRecord.unlock();
} -
To my understanding, cvCreateImage() returns a pointer a new IplImage object, created on the heap. Now you store that pointer in your QQueue. I guess you do that to later access to object via the pointer! Sure you can destroy/release the IplImage object immediately, by calling cvReleaseImage(). But be aware that the QQueue will still contain the pointer to the object you have just destroyed! Any attempt to access the object via that pointer will now cause undefined behavior (crash), because the object to which the pointer points doesn't exist anymore! Therefore it would be more logical to call cvReleaseImage() when you actually don't need the IplImage object anymore, i.e. when you can be sure that there is no pointer to that object left in your program...
-
But MuldeR,
let me discuss something.
I save the IplImage as an object reference not as a pointer.Pls
see the code below.
IplImage* opencvimageframe;
opencvimageframe = cvCreateImage(cvSize(col, row), IPL_DEPTH_8U, 1);
ImageQueue::setQueue(*opencvimageframe);void ImageQueue::setQueue(const IplImage& imageIn)
{
int i;
lockforImageRecord.lock();
ImageQueue::imageRecord.enqueue(imageIn);
lockforImageRecord.unlock();
} -
Reference and pointer is pretty much the same thing!
Indeed, in your call to ImageQueue::setQueue() you are de-referencing the pointer, by using the asterisk-operaor. So you are passing the object itself rather than a pointer to it. But: The method does NOT take an object of type IplImage by value! It takes are reference to an already existing IplImage object! If it did take an object, the copy-constructor of IplImage would be called and you would actually pass a copy (new instance!) of the object to which your pointer points. This is not the case here. Instead you are passing a reference to the exactly same object to which your pointer does point! It's the same "mistake" as returning a reference to a local object...
Why not simply make your Queue store IplImage* pointers ???
(BTW: Usually you should decide which object in your applications "owns" the pointer. This object will then also delete the pointer - or more precisely the object to which the pointer points - when it is not required anymore)
-
OK thanks, I got it.