PDA

View Full Version : Using implicit sharing to return an image as a method parameter



Luc4
21st May 2011, 23:17
Hi! I've been stuck with this for hours, I don't know why I'm doing this wrong, can't understand.
What I want to do is to create a method that returns a QImage, and pass this QImage not a the return type, but as a parameter of the method (I know I can do it other ways, but I really would like to learn why this is wrong and how it should be done).
This is more or less what I did:


QImage myImage;
myMethod(myImage);

where myMethod is defined as:


bool MyClass::myMethod(QImage& myImage)
{
...
myImage = QImage::fromData(...);
...
return true;
}

I thought that implicit sharing used this way should have assigned the new image to my myImage which, being passed by reference, is my original image. Unfortunately this is wrong as I can see. Why?

Thanks!

DanH
22nd May 2011, 00:21
What results do you get with the above?

Zlatomir
22nd May 2011, 01:00
That code should modify the original image the implicit sharing and copy on write are not used there (since you pass it by reference, not by value - so you don't have many objects that share data).

You can read more about implicit sharing here (http://doc.qt.nokia.com/latest/implicit-sharing.html#implicit-data-sharing) and as DanH said, describe the problem you have with the code, or else we can't help you very much.

Luc4
22nd May 2011, 01:47
I'm very sorry, it seems I was wrong. Maybe when I tried that way that I described, I also inadvertently introduced a second mistake. It seems that I get a segfault inside my function when I do this:


const char* _cover = QString::fromWCharArray(cover.c_str()).toStdString ().c_str();
image = QImage::fromData(QByteArray::fromBase64(QByteArray (_cover)));

instead of:


image = QImage::fromData(QByteArray::fromBase64(QByteArray (QString::fromWCharArray(cover.c_str()).toStdStrin g().c_str())));

I excluded this as a possible mistake and confused it with a problem related to the way I was passing the parameter.
Any idea why those are different?
Thanks!

EDIT: I'm maybe misunderstanding the exact meaning of implicit sharing, or misusing it. I was referring to the fact that I'm using the operator= to copy references to image data, without copying just pointers. But maybe I'm wrong in this case, and implicit sharing is not involved.

DanH
22nd May 2011, 03:43
Implict sharing is where two distinct objects (with different addresses if you were to check) share the same internal buffer (until one of them is modified). This happens for strings, images, and many other Qt types.

The two code sequences you quote are (or at least appear to be, on casual examination) equivalent. Not clear offhand why the first might fail, other than the possibility that it causes a leak and you run out of heap. But it is needlessly complex. You can go from the QString to QByteArray with toAscii().

ChrisW67
22nd May 2011, 06:23
I'm very sorry, it seems I was wrong. Maybe when I tried that way that I described, I also inadvertently introduced a second mistake. It seems that I get a segfault inside my function when I do this:


const char* _cover = QString::fromWCharArray(cover.c_str()).toStdString ().c_str();
image = QImage::fromData(QByteArray::fromBase64(QByteArray (_cover)));


The c_str() method returns a pointer to the data buffer of the std::string. The std::string is a temporary object created in the execution of the first statement: its scope ends at the completion of the enclosing statement. After that time the temporary object is destroyed and the pointer you have stored is invalid. Often you will seem to get away with this because the memory, although deallocated/destructed, still contains something that looks OK. Eventually though, you will use the invalid pointer after something else has made use of the memory it points at and BOOM!

Luc4
22nd May 2011, 10:52
Oh, I see. This is what I came up with then, far simpler:


QString _cover = QString::fromWCharArray(cover.c_str());
image = QImage::fromData(QByteArray::fromBase64(_cover.toA scii()));

seems to work now.
Thanks for your help!