Results 1 to 20 of 26

Thread: Basic question on new and delete

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Join Date
    Jan 2006
    Location
    Lincoln, NE USA
    Posts
    177
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    3
    Thanked 7 Times in 6 Posts

    Default Re: Basic question on new and delete

    Consider a program that continuously calls 'new' in a loop without calling delete. This program is 'leaking' memory for every iteration of the loop and will eventually exhaust the physical memory in the system. The fact that this memory will be released when the program terminates is irrelevant here, because the program leaks more and more memory as it runs.
    Ok, I see where you are coming from. While the program is running it is constantly leaking memory and will run out, probably crashing the program, if nothing else.

    But, after the program quites aren't the leaks still leaks... i.e., hasn't the memory been lost to the system until a reboot?

    And, doesn't QOBJECT take care of heap space that wasn't returned to memory when a) the object based on QOBJECT loses scope or b) the program quites? (Doesn't a=b?) Otherwise, if quiting the program recovers all leaked memory then the only purpose for QOBJECT is to prevent memory leaks (do garbage collection?) WHILE the program is running. Yet, I've seen several examples of programs that show a heap's size being reduced each time an app is run and then quites, so the the memory isn't returning to the heap (OS?) when the program quits.
    Last edited by GreyGeek; 30th January 2006 at 22:11.

  2. #2
    Join Date
    Jan 2006
    Location
    Mountain View, CA
    Posts
    279
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanked 42 Times in 37 Posts

    Default Re: Basic question on new and delete

    Quote Originally Posted by GreyGeek
    Ok, I see where you are coming from. While the program is running it is constantly leaking memory and will run out, probably crashing the program, if nothing else.

    But, after the program quites aren't the leaks still leaks... i.e., hasn't the memory been lost to the system until a reboot?
    I don't believe this ever to be the case, but maybe there is a (faulty) OS that proves me wrong!

    And, doesn't QOBJECT take care of heap space that wasn't returned to memory when a) the object based on QOBJECT loses scope or b) the program quites? (Doesn't a=b?) Otherwise, if quiting the program recovers all leaked memory then the only purpose for QOBJECT is to prevent memory leaks (do garbage collection?) WHILE the program is running. Yet, I've seen several examples of programs that show a heap's size being reduced each time an app is run and then quites, so the the memory isn't returning to the heap (OS?) when the program quits.
    QObject is not a garbage collector and does nothing really spectacular. All it does is delete all of it's children when it is deleted nothing more (the children will recursively delete their children, etc). This is a simple parent-child pattern and is present in many GUI toolkits, even X-Motif! Don't forget, you still have to delete the topmost parent QObject for this to work. (A toplevel QObject always has a null parent)

    When a variable goes out of scope in C++, it is destroyed. Always. This is a guarantee of the C++ runtime and nothing else. The use of Qt/QObject is irelevant. This applies to all types of variables even pointers. However, when a pointer goes out of scope, the object pointed to is not destroyed. You have to take care of this with delete. There are alternative methods you can use to avoid this like std::auto_ptr and boost smart pointers, but at the fundamental level, you must deallocate the memory yourself.

    Where QObject really helps out is when you create a GUI. A toplevel window, say derived from QMainWindow, may contain a myriad of other subwidgets within itself (Consider a complex gui that you have created in Designer). When you intsantiate your main window widget, you may do it like this:

    Qt Code:
    1. MyMainWindow* mw = new MyMainWindow(0);// note null parent
    To copy to clipboard, switch view to plain text mode 

    Within the MyMainWindow constructor, there will be code that creates and arranges many child widgets of the main window.


    When you delete the mainwindow, you would do so like this
    Qt Code:
    1. delete mw;
    To copy to clipboard, switch view to plain text mode 

    You don't worry about deleting all the pushbuttons, listboxes, labels etc that are within your main window. Why? because QObject takes care of it with its parent-child model.

    To finish, consider the following example:
    Qt Code:
    1. MyMainWindow::doSomethingSlot()
    2. {
    3. // Create a dialog and show it
    4. MyDialog* dlg = new MyDialog(this); // parented to this mainwindow
    5. ...
    6. ...
    7. dlg->exec();// display the dialog
    8. }
    To copy to clipboard, switch view to plain text mode 

    This code leaks memory - badly. Why? You may ask. "I have parented my dialog to my main window, shouldn't it be cleaned up when the main window is destroyed?". Yes, but when will the window be destroyed? Probably somewhere just before your app terminates. How many times may doSomethingSlot() be called before this happens? Every time it is called an instance of MyDialog is created that floats off into the ether after it is no longer required.

    The preferred approach here would be to delete the pointer at the end of the function or to create the dialog on the stack instead of calling 'new'.

    [Incidentally, QObject::deleteLater() is often a better alternative to a straightforward 'delete' on a QObject, but that's another story!]
    Last edited by Chicken Blood Machine; 30th January 2006 at 23:14.

  3. #3
    Join Date
    Jan 2006
    Location
    Lincoln, NE USA
    Posts
    177
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    3
    Thanked 7 Times in 6 Posts

    Default Re: Basic question on new and delete

    Quote Originally Posted by Chicken Blood Machine
    ...snip...
    Where QObject really helps out is when you create a GUI. A toplevel window, say derived from QMainWindow, may contain a myriad of other subwidgets within itself (Consider a complex gui that you have created in Designer). When you intsantiate your main window widget, you may do it like this:

    Qt Code:
    1. MyMainWindow* mw = new MyMainWindow(0);// note null parent
    To copy to clipboard, switch view to plain text mode 

    Within the MyMainWindow constructor, there will be code that creates and arranges many child widgets of the main window.


    When you delete the mainwindow, you would do so like this
    Qt Code:
    1. delete mw;
    To copy to clipboard, switch view to plain text mode 

    You don't worry about deleting all the pushbuttons, listboxes, labels etc that are within your main window. Why? because QObject takes care of it with its parent-child model.
    Well, here is the main function, from my main.cpp, from my Homestead application:
    Qt Code:
    1. int main( int argc, char * argv[] ) {
    2. QString strRejected = "";
    3. QApplication app(argc, argv);
    4. app.setQuitOnLastWindowClosed(false);
    5. dlgLogin dlg;
    6. if( dlg.exec() == QDialog::Accepted ){
    7. QSqlDatabase hapdb = QSqlDatabase::addDatabase(DBDRIVER);
    8. hapdb.setHostName(DBHOST);
    9. hapdb.setDatabaseName(DBNAME);
    10. hapdb.setUserName(dlg.dui.leUserName->text());
    11. hapdb.setPassword(dlg.dui.leUserPassword->text());
    12. if ( hapdb.open() ) {
    13. homestead ht;
    14. ht.RevID = dlg.dui.leUserName->text();
    15. ht.show();
    16. app.setQuitOnLastWindowClosed(true);
    17. return app.exec();
    18. } else {
    19. strRejected = QString("The Login was rejected because: %1").arg(hapdb.lastError().text()).toLatin1();
    20. QMessageBox::information(0,"Login Rejected!",strRejected,
    21. QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
    22. return 1;
    23. }
    24. } else {
    25. strRejected = QString("User Canceled the login!").toLatin1();
    26. QMessageBox::information(0,"Login Rejected!",strRejected,
    27. QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
    28. return 2;
    29. }
    30. }
    To copy to clipboard, switch view to plain text mode 
    As I understand your comments, since "dlg" is called only once, and that call is in this function, its memory will be recovered when main goes out of scope (i.e., the app closes). And, hapdb is also instantiated only once so its memory, too, will be reclaimed when the app closes. The ht object, where Homestead really operates, is also instantiated only once and like the others, the memory it uses is returned to the OS when the app closes. So, I don't need as the last three lines of main():
    Qt Code:
    1. delete ht;
    2. delete hapdb;
    3. delete dlg;
    To copy to clipboard, switch view to plain text mode 
    because none of these objects leak memory, even though dlg has a parent:
    Qt Code:
    1. class dlgLogin : public QDialog
    2. {
    3. Q_OBJECT
    4. public:
    5. Ui::dlgLoginUi dui;
    6. dlgLogin()
    7. {
    8. dui.setupUi(this);
    9. dui.leUserName->setText("your revid");
    10. dui.leUserPassword->setText("");
    11. dui.leUserName->setFocus();
    12. dui.leUserName->selectAll();
    13. }
    14. };
    To copy to clipboard, switch view to plain text mode 
    but homestead does not...
    Qt Code:
    1. class homestead : public QMainWindow
    2. {
    3. Q_OBJECT
    4. public:
    5. homestead(QWidget *parent = 0);
    6. ...
    To copy to clipboard, switch view to plain text mode 

    Right?

  4. #4
    Join Date
    Jan 2006
    Location
    Mountain View, CA
    Posts
    279
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanked 42 Times in 37 Posts

    Default Re: Basic question on new and delete

    Quote Originally Posted by GreyGeek
    Well, here is the main function, from my main.cpp, from my Homestead application:
    Qt Code:
    1. int main( int argc, char * argv[] ) {
    2. QString strRejected = "";
    3. QApplication app(argc, argv);
    4. app.setQuitOnLastWindowClosed(false);
    5. dlgLogin dlg;
    6. if( dlg.exec() == QDialog::Accepted ){
    7. QSqlDatabase hapdb = QSqlDatabase::addDatabase(DBDRIVER);
    8. hapdb.setHostName(DBHOST);
    9. hapdb.setDatabaseName(DBNAME);
    10. hapdb.setUserName(dlg.dui.leUserName->text());
    11. hapdb.setPassword(dlg.dui.leUserPassword->text());
    12. if ( hapdb.open() ) {
    13. homestead ht;
    14. ht.RevID = dlg.dui.leUserName->text();
    15. ht.show();
    16. app.setQuitOnLastWindowClosed(true);
    17. return app.exec();
    18. } else {
    19. strRejected = QString("The Login was rejected because: %1").arg(hapdb.lastError().text()).toLatin1();
    20. QMessageBox::information(0,"Login Rejected!",strRejected,
    21. QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
    22. return 1;
    23. }
    24. } else {
    25. strRejected = QString("User Canceled the login!").toLatin1();
    26. QMessageBox::information(0,"Login Rejected!",strRejected,
    27. QMessageBox::Ok,QMessageBox::NoButton,QMessageBox::NoButton);
    28. return 2;
    29. }
    30. }
    To copy to clipboard, switch view to plain text mode 
    As I understand your comments, since "dlg" is called only once, and that call is in this function, its memory will be recovered when main goes out of scope (i.e., the app closes). And, hapdb is also instantiated only once so its memory, too, will be reclaimed when the app closes. The ht object, where Homestead really operates, is also instantiated only once and like the others, the memory it uses is returned to the OS when the app closes. So, I don't need as the last three lines of main():
    Qt Code:
    1. delete ht;
    2. delete hapdb;
    3. delete dlg;
    To copy to clipboard, switch view to plain text mode 
    That would not even compile. None of the variables you mentioned are pointer variables, so how could you ever call delete on them? Your code (above) as listed will not leak any memory, because all objects are created on the stack.

    because none of these objects leak memory, even though dlg has a parent:
    Qt Code:
    1. class dlgLogin : public QDialog
    2. {
    3. Q_OBJECT
    4. public:
    5. Ui::dlgLoginUi dui;
    6. dlgLogin()
    7. {
    8. dui.setupUi(this);
    9. dui.leUserName->setText("your revid");
    10. dui.leUserPassword->setText("");
    11. dui.leUserName->setFocus();
    12. dui.leUserName->selectAll();
    13. }
    14. };
    To copy to clipboard, switch view to plain text mode 
    Dialog does NOT have a parent. Look how you instantiated it

    Qt Code:
    1. dlgLogin dlg; // <- No parent
    To copy to clipboard, switch view to plain text mode 

    It's constructor does not event have a QWidget* 'parent' parameter, so there is no way to create a dlgLogin object with a parent (even if you wanted to).

    What makes you think that it has a parent?

    but homestead does not...
    Qt Code:
    1. class homestead : public QMainWindow
    2. {
    3. Q_OBJECT
    4. public:
    5. homestead(QWidget *parent = 0);
    6. ...
    To copy to clipboard, switch view to plain text mode 

    Right?
    Correct (but not for the reason that you have stated). Your homestead object does not have a parent, because you declared it like this:
    Qt Code:
    1. homestead ht;
    To copy to clipboard, switch view to plain text mode 

    If you wanted it to have a parent, you would have declared it like this:
    Qt Code:
    1. ...
    2. homestead ht(parent); // Parent is some QWidget*, declared further up
    To copy to clipboard, switch view to plain text mode 

    In both cases, the fact theat you declared your widgets with no parent is fine, because you are ensuring their destruction by declaring them on the stack (not as pointers allocated with 'new') and therefore, they are destroyed when they run out of scope.

  5. #5
    Join Date
    Jan 2006
    Location
    Lincoln, NE USA
    Posts
    177
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    3
    Thanked 7 Times in 6 Posts

    Default Re: Basic question on new and delete

    Quote Originally Posted by Chicken Blood Machine
    That would not even compile. None of the variables you mentioned are pointer variables, so how could you ever call delete on them? Your code (above) as listed will not leak any memory, because all objects are created on the stack.
    That I knew, I was just supposing that if they were created by "new" would it matter if they were deleted using the delete operator because they were going out of scope anyway if, as you say, the OS will always get the memory back.


    Dialog does NOT have a parent. Look how you instantiated it

    Qt Code:
    1. dlgLogin dlg; // <- No parent
    To copy to clipboard, switch view to plain text mode 

    It's constructor does not event have a QWidget* 'parent' parameter, so there is no way to create a dlgLogin object with a parent (even if you wanted to).

    What makes you think that it has a parent?
    Because it inherited from QDialog?
    class dlgLogin : public QDialog

    An ancestor isn't a parent?
    (I told you I was new to C++)

    Correct (but not for the reason that you have stated). Your homestead object does not have a parent, because you declared it like this:
    Qt Code:
    1. homestead ht;
    To copy to clipboard, switch view to plain text mode 

    If you wanted it to have a parent, you would have declared it like this:
    Qt Code:
    1. ...
    2. homestead ht(parent); // Parent is some QWidget*, declared further up
    To copy to clipboard, switch view to plain text mode 

    In both cases, the fact theat you declared your widgets with no parent is fine, because you are ensuring their destruction by declaring them on the stack (not as pointers allocated with 'new') and therefore, they are destroyed when they run out of scope.
    So, using "new" as shown below means that "ui.gridMultiProp" is a parent to *model ??
    Qt Code:
    1. QSqlQueryModel *model = new QSqlQueryModel(ui.gridMultiProp);
    To copy to clipboard, switch view to plain text mode 
    Pardon the dumb questions but you'll dealing with someone who has read perhaps too much and it's all jumbled up inside?
    It's amazing that I can, using QT, write the app I did and that it works.

  6. #6
    Join Date
    Jan 2006
    Location
    Mountain View, CA
    Posts
    279
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanked 42 Times in 37 Posts

    Default Re: Basic question on new and delete

    Quote Originally Posted by GreyGeek
    That I knew, I was just supposing that if they were created by "new" would it matter if they were deleted using the delete operator because they were going out of scope anyway if, as you say, the OS will always get the memory back.
    Ok, then no, it wouldn't matter. As a matter of good practice, I would delete them anyway though.

    Because it inherited from QDialog?
    class dlgLogin : public QDialog

    An ancestor isn't a parent?
    (I told you I was new to C++)
    No, QDialog is its baseclass, not its parent. The parent is the object you pass as the QWidget* parameter (which can be NULL). 'Baseclass', 'superclass' or 'inherited class' are names for the same C++ OO constructs. 'Parent' (in this context) is a Qt construct and refers to ownership, not inheritance. Reading the comprehensive documentation of QObject will explain it more.

    So, using "new" as shown below means that "ui.gridMultiProp" is a parent to *model ??
    Qt Code:
    1. QSqlQueryModel *model = new QSqlQueryModel(ui.gridMultiProp);
    To copy to clipboard, switch view to plain text mode 
    That's correct.

    Pardon the dumb questions but you'll dealing with someone who has read perhaps too much and it's all jumbled up inside?
    It's amazing that I can, using QT, write the app I did and that it works.
    It is amazing. Did you check your prog for memory leaks
    Actually, it's a very bad idea to use Qt to learn C++ (not suggesting that you did it this way). It is much better to learn C++ and get confident with it (warts and all), then start using Qt to see how much easier it makes your life! The QObject parent-child model along with the references counted non-QObjects really help cut down on the amount of memory management that you have to worry about (but you still must be wary).

  7. #7
    Join Date
    Jan 2006
    Location
    Scandinavia
    Posts
    62
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    5
    Thanked 2 Times in 1 Post

    Default Re: Basic question on new and delete

    Once the program has terminated. The OS (Linux and Windows) will be able to use the memory again. Definition of memory leak is during the lifetime of the program.

    However, the OS might not be so nice for awhile if the memory leaking program took up ALL memory resources until it finally crashed. But the first example is a safe example. He makesnew object... (usually doing other stuff too ;-) and then the application quits, and the memory - when it is needed. Will be re-used by the OS.

    Another issue is memory fragmentation, which can be a bigger problem on Windows I fear.

  8. #8
    Join Date
    Feb 2006
    Posts
    91
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    4

    Default Re: Basic question on new and delete

    Welll I have a very basic query on this matter.. What happens if the application is run continuously where it will have several instances of new.
    Lets say at the end of the program it says:
    Do you want to quit or continue ?

    If the user wants to continue then the main application has not been quit.. so all the instances of "new" that were originally there will again be made..as the program will again run from the beginning .
    In such case does QT takes care of freeing the memory..or we have to manually free up all the memory taken by the object ..

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    28
    Thanked 976 Times in 912 Posts

    Default Re: Basic question on new and delete

    Quote Originally Posted by ct
    In such case does QT takes care of freeing the memory..or we have to manually free up all the memory taken by the object ..
    Qt will delete only objects derived from QObject that have a parent and only if their parent gets deleted.

  10. #10
    Join Date
    Feb 2006
    Posts
    91
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    4

    Default Re: Basic question on new and delete

    so say in case of something like messenger, where one logs out all the objects needs to be manuallly freed so that new instances could be formed for the new sign in procedure ..

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows
    Thanks
    28
    Thanked 976 Times in 912 Posts

    Default Re: Basic question on new and delete

    Quote Originally Posted by ct
    so say in case of something like messenger, where one logs out all the objects needs to be manuallly freed so that new instances could be formed for the new sign in procedure ..
    If they aren't QObjects or they have no parents, yes.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.