简体   繁体   中英

2d QList Memory Leak

I created this 2D Qlist. Code "works" but when I consider a bit deeper the syntax it leaves me wondering whether this code leads to memory leak.

I would be great if someone could shed some light on whether this code leads to a mem leak or not. If it does, WHY and how to fix?

My Specific concerns are question marked as Q1,Q2,Q3,Q4 in code comments.

Also, how should I destroy some rows from lszq2DList and ultimately how should I destroy lszq2DList.

//The 2d data sructure. Each row will be a QStringList.
QList<QStringList> lszq2DList; 

//The variable "emptyTempList" is a concern to me.  
//Q1:: Isn't "emptyTempList" just a pointer to some allocated place in memory?  
//If so, I imagine it points to some data structure allocated in memory.
//Or does this not allocate anything?  I have a feeling it does not.
QStringList emptyTempList;   //I use it in my scheme to make a 2D data struct.

for(int i=0; i<3; i++){
    //Q2: Because I am in a loop and reusing the same pointer "emptyTempList", 
    //aren't i pointing to the same thing?
    //If I think about this, each item in my Qlist (each row) should be 
    //pointing to the same place in memory.  To whatever "emptyTempList"
    //points to.    
    //Of course, this is not the case.  What is really going on in line bellow?
    lszq2DList += emptyTempList;  //I'm no really pointing to anything am I?  

    QString szqTempString;  //Q3: Gets trashed when out of scope?
    for(int j=0; j<3; j++){
        szqTempString.clear();
        szqTempString = "jazz";

            //QString value gets copied into datastructure?
        lszq2DList[i] += szqTempString;  
    }
}


QStringList emptyTempList2;
emptyTempList2 += "blues";
emptyTempList2 += "blues";
emptyTempList2 += "blues";

//I'll add another row.
lszq2DList += emptyTempList2;  
//Q4: lszq2DList[3] does not point to emptyTempList2, right?
//Instead it copies all the strings 
//from to emptyTempList2 to lszq2DList[3], right?

QList, QStringList, and QString are all "implicitly shared" which basically means "copy on write". For example:

QStringList someFunction() {
    QStringList list;
    QString str("Hello World!");

    for(int x = 0;x < 100; ++x) {
        list << str;
    }

    QStringList list2 = list;
    QStringList list3 = list;
    QStringList list4 = list;

    return list4;
}

QStringList list5 = someFunction();

And after all that you still only have the string "Hello World!" in memory one time. You can read more about it Here . As a general rule with Qt classes "objects which inherit from QObject go on the heap, otherwise they go on the stack". There are exceptions, but very few and implicitly shared classes should always go on the stack.

I would suggest checking for memory leaks using something similar to valgrind or other.

However, when memory "leaks," it means that that memory was simply not freed after use and all access has been removed. This essentially means that there is memory allocated on the heap, for example, but nothing has access to it so it's virtually useless memory. For instance, when you dynamically allocate memory to a pointer using "new," you must "delete" so the memory is freed. I will give an example.

char * ptr = new char;
ptr = NULL; // Memory leak
delete ptr; // This is useless since it no longer points to the memory location

However, this is totally valid

char * ptr = new char;
delete ptr;
ptr = NULL;

The reason the first one leaks is because you did not "delete" the memory. Since the pointer location was changed to "NULL" before delete was called, it did not know to free memory at whatever address was associated with the pointer before setting it to NULL.

That said, however, it does not look like your code would have any memory leaks in it (nothing is being dynamically allocated). Since it looks like all of your variables are being allocated on the stack, the system manages this memory for you - once these objects go out of scope (if this is in main() then when program exits), they will be popped off the stack by system. This is assuming, however, that QList is not leaking.

EDIT

Remember, when you create instances of a class, the memory allocated is on the stack (memory freed instantly upon leaving scope) which you do not need to worry about. Dynamic allocation (allocation/deallocation of memory using new/delete) is stored on the heap (persistent memory for our purposes). So you should not worry about leaks for memory which you did not dynamically allocate.

EDIT 2

In regards to using heap vs. stack, use stack whenever possible. The less memory you have to manage the better (and less bug prone you will be). As far as question two is concerned, you are not using pointers. What you are doing is copying the value of emptyTempList and not reusing its memory location (since its not a pointer). You have to use the & operator to extract the memory address from your object since, again, it's not a pointer.

Hope this helps!

Regards,
Dennis M.

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