简体   繁体   中英

How to free QByteArray created with fromRawData()

The docs state the following :

QByteArray does not take ownership of data, so the QByteArray destructor will never delete the raw data, even when the last QByteArray referring to data is destroyed.

With that in mind, how does one free a QByteArray created in this way?

Conceptually - I'd guess calling free() on the pointer via data() or constData() , but I'm really not sure... here's a code sample illustrating the use case:

void doTest() {
    QByteArray qba = partOne();
    partTwo(qba);
    finished(qba);
}

QByteArray partOne() {

    char *dataPtr = (char *)malloc(64);
    //do some stuff to dataPtr

    QByteArray qba = QByteArray::fromRawData(dataPtr, 64);
    //do some stuff to qba
    return qba;
}

void partTwo(QByteArray qba) {
    //do more stuff to qba
}

void finished(QByteArray qba) {
    //this?
    free((void *)qba.constData());
}

how does one free a QByteArray created in this way?

It's simple - one doesn't. The byte array doesn't take ownership of the data, so you don't "free it" from the byte array.

If there is a necessity to free the data, that responsibility should fall to the code that allocated the data. After you are done with the byte array and there exist no further references to it.

The data may or may not be "free-able", thus you should not try to free it from the byte array. Whatever mechanism allocated the data should handle its deallocation.

memory allocation
    byte array construction
        byte array usage  
    byte array destruciton
memory deallocation

Edit: Keep in mind that with COW there is a big difference between "do stuff to" and "do stuff with" as in you reading or writing, because the moment you write, COW kicks in, the underlying data will be copied and the changes will be applied to it rather than the original data. Naturally, this only happens if more than one byte array instances implicitly share the data, as for example it would be in partTwo() . If you don't want this to happen, pass by reference rather than by copy. Obviously, if COW kicks in, it would be a problem if you free the memory from data() , because you will free the new memory that was allocated by the byte array, and your original allocation would turn into a memory leak. Thus the solution below provisions against that possibility.

void doTest() {
    char *dataPtr = (char *)malloc(64);
    //do some stuff to dataPtr
    {
        QByteArray qba = partOne(dataPtr);
        partTwo(qba);
    } // qba dies here
    free(dataPtr);
}  

QByteArray partOne(char *dataPtr) {
    QByteArray qba = QByteArray::fromRawData(dataPtr, 64);
    //do some stuff to qba
    return qba;
}

void partTwo(QByteArray qba) {
    //do more stuff to qba
}

There's no need for you to manage the memory manually at all:

QByteArray partOne() {
  QByteArray qba(64, Qt::Uninitialized);
  auto dataPtr = qba();
  // use dataPtr
  // do some stuff to qba
  return qba;
}

fromRawData doesn't take ownership, so memory should be freed by object which owns data you need to free.

Conceptually - I'd guess calling free() on the pointer via .data() or .constData(), but I'm really not sure...

It's incorrect as you cannot guarantee that QByteArray doesn't own the data. Eg if you modify the content of the QByteArray the deep copy will be created and this copy will be freed by QByteArray destructor:

A subsequent attempt to modify the contents of the returned QByteArray or any copy made from it will cause it to create a deep copy of the data array before doing the modification. This ensures that the raw data array itself will never be modified by QByteArray.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM