Page 1 of 2 12 LastLast
Results 1 to 20 of 27

Thread: How to correctly re-assign a pointer?

  1. #1
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Question How to correctly re-assign a pointer?

    Hello!

    I started another topic yesterday, but I guess it went far into detail.
    My questions comes down to this:

    How can I correctly re-assign a pointer?

    In my case, I have a QtDesigner-Layout, which creates a QTableView:

    Qt Code:
    1. public:
    2. QTableView *tableView;
    3. ...
    4. void setupUi(QDialog *AddressBook)
    5. {
    6. tableView = new QTableView(AddressBook);
    7. ...
    8. }
    To copy to clipboard, switch view to plain text mode 

    In the class which uses this layout I want to pass a pointer to a pre-defined QTableView to the one created by the layout.

    AddressBook-class:
    Qt Code:
    1. AddressBook::AddressBook(DataManager* dmgr, QWidget *parent): QDialog(parent)
    2. {
    3. ...
    4. tableView = dmgr->customerTableView();
    5. ...
    6. }
    To copy to clipboard, switch view to plain text mode 

    DataManager-class

    Qt Code:
    1. ...
    2. QTableView *m_customerTableView;
    3. QTableView *customerTableView();
    4. ...
    5. m_customerTableView = new QTableView;
    6. ...
    7. QTableView *DataManager::customerTableView()
    8. {
    9. return m_customerTableView;
    10. }
    11. ...
    To copy to clipboard, switch view to plain text mode 

    I guess to avoid memory leaks I have to delete the original tableView created by QtDesigner.

    I tried the following but could get it running, since I am not so familiar with pointers yet. (coming from Java) So there could be a misunderstanding on how pointers work.

    In AddressBook-class:

    Qt Code:
    1. delete tableView;
    2. QTableView *tableView = dmgr->customerTableView();
    To copy to clipboard, switch view to plain text mode 

    I hope you can help me.

    Kind regards,
    HomeR

  2. #2
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: How to correctly re-assign a pointer?

    You are shadowing your member pointer.
    There is no need to redeclare it:
    Qt Code:
    1. delete tableView;
    2. /*QTableView * */ tableView = dmgr->customerTableView();
    To copy to clipboard, switch view to plain text mode 
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  3. #3
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Default Re: How to correctly re-assign a pointer?

    Thanks for you anwser.
    I tried what you said, but it's still not working.

    Does shadowing mean, that a global variable is hidden because a local variable is used instead?

    What exactly happens here?
    Qt Code:
    1. delete tableView;
    2. /*QTableView * */ tableView = dmgr->customerTableView();
    To copy to clipboard, switch view to plain text mode 

    As far as I unterstand, delete tableView does remove the QTableView object created in the QtDesigner-file ui_addressbook.h :

    Qt Code:
    1. class Ui_AddressBook
    2. {
    3. public:
    4. QTableView *tableView;
    5. ..
    6. }
    To copy to clipboard, switch view to plain text mode 

    Then my prepared QTableView returned by dmgr->customerTableView(); is assigned - but assigned to what? There is no other variable named tableView existing, I guess. Do I have to define an additional one with the same name in
    AddressBook.h ?

    Right now my code is

    Qt Code:
    1. delete tableView;
    2. Q_CHECK_PTR(tableView);
    3. Q_CHECK_PTR(dmgr->customerTableView());
    4. tableView = dmgr->customerTableView();
    To copy to clipboard, switch view to plain text mode 

    Why does die application not quit on "Q_CHECK_PTR(tableView)" after "delete tableView" ?

  4. #4
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: How to correctly re-assign a pointer?

    I tried what you said, but it's still not working.
    please define what 'not working' mean here.

    Does shadowing mean, that a global variable is hidden because a local variable is used instead?
    Yes, but instead of 'global' here its in the class scope. (so its only visible in the scope of the class).

    What exactly happens here?
    Well, unless there is more code that I havn't seen then:
    In the very first code segment you posted in the firt post, you declare
    Qt Code:
    1. QTableView *tableView
    To copy to clipboard, switch view to plain text mode 
    As a class member.
    So if this code:
    Qt Code:
    1. delete tableView;
    2. /*QTableView * */ tableView = dmgr->customerTableView();
    To copy to clipboard, switch view to plain text mode 
    Is in the same clase, then tableViewe is already defined, and defining it again in the method, would shadow the one defined in the class header, and the address will be assigned to the local shadow, which gets destroyed when the method exits.
    Note - the POINTER gets destroyed, but the address allocated still lives - and this called a dangling pointer - which is a memory leak - since you can't get it and delete it any more. (gets deleted when the memory of the application is returned)

    Do I have to define an additional one with the same name in
    AddressBook.h
    No, and if you would, you would get a complication error.


    As far as I unterstand, delete tableView does remove the QTableView object created in the QtDesigner-file ui_addressbook.h :
    Yes and no.
    'delete' deletes the object pointed to by the poiter (calling its destructor etc).
    In your case, its ture, that the first allocation is done in the ui file.

    Then my prepared QTableView returned by dmgr->customerTableView(); is assigned - but assigned to what? There is no other variable named tableView existing, I guess.
    Don't guess - be sure!

    Why does die application not quit on "Q_CHECK_PTR(tableView)" after "delete tableView" ?
    because delete does not set the deleted pointer to NULL.
    So you should do:
    delete tableView;
    Q_CHECK_PTR(tableView); //will go through, since tableViewer is not NULL (but filled with garbage)
    tableView = NULL;
    Q_CHECK_PTR(tableView); // this will assert!
    Q_CHECK_PTR(dmgr->customerTableView());
    tableView = dmgr->customerTableView();
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  5. The following user says thank you to high_flyer for this useful post:

    homerun4711 (3rd January 2011)

  6. #5
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Default Re: How to correctly re-assign a pointer?

    Thanks for your explanations, some things concerning pointers became clearer to me.

    please define what 'not working' mean here.
    My plan is to show a model listing customers.
    This is defined in the QtDesigner-file, which is inherited by my AddressBook-class.

    ui_addressbook.h
    Qt Code:
    1. QTableView *tableView
    2. ...
    3. tableView = new QTableView(AddressBook);
    4. tableView->setObjectName(QString::fromUtf8("tableView"));
    To copy to clipboard, switch view to plain text mode 

    This is defined in the QtDesigner-file, which is inherited by my AddressBook-class.

    Don't guess - be sure!
    The AddressBook-class has no other member using the same name. I am sure

    After deleting the object created by the QtDesigner-File using
    Qt Code:
    1. delete tableView;
    To copy to clipboard, switch view to plain text mode 
    now the area beforehand used by the table in my user interface is empty. Not even an empty QTableView. Well, this is
    expected as far as I unterstand this now.

    Here is some more code from the DataManager-class:

    DataManager.h

    Qt Code:
    1. QTableView *customerTableView();
    2. QTableView *m_customerTableView;
    3. QStandardItemModel *model_customer;
    To copy to clipboard, switch view to plain text mode 

    DataManager.cpp
    Qt Code:
    1. model_customer = new QStandardItemModel;
    2. model_customer->setObjectName("Customers");
    3. ....
    4. m_customerTableView = new QTableView;
    5. m_customerTableView->setModel(model_customer);
    6.  
    7. QTableView *DataManager::customerTableView()
    8. {
    9. return m_customerTableView;
    10. }
    11.  
    12. ...
    To copy to clipboard, switch view to plain text mode 

    Well, using
    Qt Code:
    1. delete tableView;
    2. tableView = dmgr->customerTableView();
    To copy to clipboard, switch view to plain text mode 

    to set the prepared QTableView from my DataManager-class does not show the QTableView in the GUI.

    Sorry, I know I should ask more precise questions, but I hope you can help me.
    Just tell me if you need more informations. Thanks!


    Added after 13 minutes:


    Ok, I rewrote the function returning the QTableWidget, it's working now.
    I forgot to pass the correct parent. *stupid*stupid*

    Soultion was
    Qt Code:
    1. QTableView *DataManager::customerTableView(QWidget* parent)
    2. {
    3. m_customerTableView = new QTableView(parent);
    4. m_customerTableView->setModel(model_customer);
    5. m_customerTableView->setObjectName(QString::fromUtf8("tableView"));
    6. m_customerTableView->setGeometry(QRect(10, 10, 701, 191));
    7. return m_customerTableView;
    8. }
    To copy to clipboard, switch view to plain text mode 

    and to call it using

    Qt Code:
    1. tableView = dmgr->customerTableView(this);
    To copy to clipboard, switch view to plain text mode 

    Thanks a lot for your help and your explanations!
    Last edited by homerun4711; 3rd January 2011 at 17:44.

  7. #6
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: How to correctly re-assign a pointer?

    most welcome!
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  8. #7
    Join Date
    Nov 2010
    Posts
    97
    Thanks
    6
    Thanked 11 Times in 11 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to correctly re-assign a pointer?

    Quote Originally Posted by high_flyer View Post
    You are shadowing your member pointer.
    I understand what you're saying but I've never heard that word used to describe what you're describing. I think a more common term there might be "hiding". Could matter in google searches for anyone trying to learn more about it.

    Quote Originally Posted by homerun4711 View Post
    Does shadowing mean, that a global variable is hidden because a local variable is used instead?
    In C++, if you declare a new name within a sub-scope of any scope that already has that name you will cause the old one to be hidden. This can include the global scope but can also include any other scope that you are currently in. With class members this has some interesting and sometimes confusing implications. You'll want to learn more about it.
    This rude guy who doesn't want you to answer his questions.

    Note: An "expert" here is just someone that's posted a lot.

    "The fact of where you do the encapsulation is meaningless." - Qt Certified Developer and forum moderator

  9. #8
    Join Date
    Dec 2010
    Location
    US, Washington State
    Posts
    54
    Thanks
    3
    Thanked 7 Times in 7 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to correctly re-assign a pointer?

    Quote Originally Posted by homerun4711 View Post
    The AddressBook-class has no other member using the same name. I am sure
    You should still check, dereferencing a NULL pointer is bad. What works today may not work tomorrow or next month after you've made changes to the code, and checking the returned pointer will find the problem immediately. If you know that the pointer is 100% always suppose to return a value other than NULL then use can use Q_ASSERT, otherwise use if statements.

    Quote Originally Posted by homerun4711 View Post
    Well, using
    Qt Code:
    1. delete tableView;
    2. tableView = dmgr->customerTableView();
    To copy to clipboard, switch view to plain text mode 
    Ok, I rewrote the function returning the QTableWidget, it's working now.
    I forgot to pass the correct parent. *stupid*stupid*

    Soultion was
    Qt Code:
    1. QTableView *DataManager::customerTableView(QWidget* parent)
    2. {
    3. m_customerTableView = new QTableView(parent);
    4. m_customerTableView->setModel(model_customer);
    5. m_customerTableView->setObjectName(QString::fromUtf8("tableView"));
    6. m_customerTableView->setGeometry(QRect(10, 10, 701, 191));
    7. return m_customerTableView;
    8. }
    To copy to clipboard, switch view to plain text mode 
    and to call it using
    Qt Code:
    1. tableView = dmgr->customerTableView(this);
    To copy to clipboard, switch view to plain text mode 
    This is bad juju. What happens if you call "delete tableView" without the next call to "customerTableView"? What state is m_customerTableView variable left in? How about if there are other member functions of DataManager that work with m_customerTableView and what it points to is deleted outside of the DataManger class?

    A slightly better implementation than the current.
    Qt Code:
    1. QTableView * DataManager::DeleteCustomerTableView(void)
    2. {
    3. delete m_customerTableView;
    4. m_customerTableView = NULL;
    5. return m_customerTableview;
    6. }
    7. QTableView *DataManager::customerTableView(QWidget* parent)
    8. {
    9. DeleteCustomerTableView();
    10. m_customerTableView = new QTableView(parent);
    11. m_customerTableView->setModel(model_customer);
    12. m_customerTableView->setObjectName(QString::fromUtf8("tableView"));
    13. m_customerTableView->setGeometry(QRect(10, 10, 701, 191));
    14. return m_customerTableView;
    15. }
    16. ...
    17. // delete tableView; DataManager handles the delete, this call not needed.
    18. tableView = dmgr->customerTableView(this);
    To copy to clipboard, switch view to plain text mode 
    There is still a problem with the code above as it is possible to dereference a returned NULL pointer from new'd QTableView (out of memory).

    Rules for staying out of trouble when programming in C/C++.
    1) If a function returns an error code, check the returned value, never assume the function call was successful.
    2) Always check returned pointers to ensure they are not NULL, handle accordingly.
    3) If a class owns a pointer, don't delete the pointer outside of the class.
    4) If a class hands ownership of pointer to another class, apply rule 3.

    Qt's object ownership tree might blur #3 a bit. Still DataManager should handle the deletion of the object, so added DeleteCustomerTableView for this purpose.
    Qt Code:
    1. tableView = dmgr->DeleteCustomerTableView();
    To copy to clipboard, switch view to plain text mode 

    Writing defensible code is TEDIOUS WORK (actually it's second nature if you do it all time) and adds lots of extra lines of code, however the benefits are huge. When the app starts crashing during development the error will be easier to find. When the application is deployed to outside users (with varying system architecture) defensible coding will enable you to determine the problem. Defensible coding allows errors to be handled gracefully, did a new call return NULL (out of memory) then maybe some resources can be freed and new called again. Do you check the return value from QObject::connect(...), if not how do you now the connection was successful?

    Quote Originally Posted by homerun4711 View Post
    The AddressBook-class has no other member using the same name. I am sure
    You should still check, dereferencing a NULL pointer is bad. What works today may not work tomorrow or next month after you've made changes to the code, and checking the returned pointer will find the problem immediately. If you know that the pointer is 100% always suppose to return a value other than NULL then use can use Q_ASSERT, otherwise use if statements.

    Quote Originally Posted by homerun4711 View Post
    Well, using
    Qt Code:
    1. delete tableView;
    2. tableView = dmgr->customerTableView();
    To copy to clipboard, switch view to plain text mode 
    Ok, I rewrote the function returning the QTableWidget, it's working now.
    I forgot to pass the correct parent. *stupid*stupid*

    Soultion was
    Qt Code:
    1. QTableView *DataManager::customerTableView(QWidget* parent)
    2. {
    3. m_customerTableView = new QTableView(parent);
    4. m_customerTableView->setModel(model_customer);
    5. m_customerTableView->setObjectName(QString::fromUtf8("tableView"));
    6. m_customerTableView->setGeometry(QRect(10, 10, 701, 191));
    7. return m_customerTableView;
    8. }
    To copy to clipboard, switch view to plain text mode 
    and to call it using
    Qt Code:
    1. tableView = dmgr->customerTableView(this);
    To copy to clipboard, switch view to plain text mode 
    This is bad juju. What happens if you call "delete tableView" without the next call to "customerTableView"? What state is m_customerTableView variable left in? How about if there are other member functions of DataManager that work with m_customerTableView and what it points to is deleted outside of the DataManger class?

    A slightly better implementation than the current.
    Qt Code:
    1. QTableView * DataManager::DeleteCustomerTableView(void)
    2. {
    3. delete m_customerTableView;
    4. m_customerTableView = NULL;
    5. return m_customerTableview;
    6. }
    7. QTableView *DataManager::customerTableView(QWidget* parent)
    8. {
    9. DeleteCustomerTableView();
    10. m_customerTableView = new QTableView(parent);
    11. m_customerTableView->setModel(model_customer);
    12. m_customerTableView->setObjectName(QString::fromUtf8("tableView"));
    13. m_customerTableView->setGeometry(QRect(10, 10, 701, 191));
    14. return m_customerTableView;
    15. }
    16. ...
    17. // delete tableView; DataManager handles the delete, this call not needed.
    18. tableView = dmgr->customerTableView(this);
    To copy to clipboard, switch view to plain text mode 
    There is still a problem with the code above as it is possible to dereference a returned NULL pointer from new'd QTableView (out of memory).

    Rules for staying out of trouble when programming in C/C++.
    1) If a function returns an error code, check the returned value, never assume the function call was successful.
    2) Always check returned pointers to ensure they are not NULL, handle accordingly.
    3) If a class owns a pointer, don't delete the pointer outside of the class.
    4) If a class hands ownership of pointer to another class, apply rule 3.

    Qt's object ownership tree might blur #3 a bit. Still DataManager should handle the deletion of the object, so added DeleteCustomerTableView for this purpose.
    Qt Code:
    1. tableView = dmgr->DeleteCustomerTableView();
    To copy to clipboard, switch view to plain text mode 

    Writing defensible code is TEDIOUS WORK (actually it's second nature if you do it all time) and adds lots of extra lines of code, however the benefits are huge. When the app starts crashing during development the error will be easier to find. When the application is deployed to outside users (with varying system architecture) defensible coding will enable you to determine the problem. Defensible coding allows errors to be handled gracefully, did a new call return NULL (out of memory) then maybe some resources can be freed and new called again. Do you check the return value from QObject::connect(...), if not how do you now the connection was successful?

    Quote Originally Posted by homerun4711 View Post
    The AddressBook-class has no other member using the same name. I am sure
    You should still check, dereferencing a NULL pointer is bad. What works today may not work tomorrow or next month after you've made changes to the code, and checking the returned pointer will find the problem immediately. If you know that the pointer is 100% always suppose to return a value other than NULL then use can use Q_ASSERT, otherwise use if statements.

    Quote Originally Posted by homerun4711 View Post
    Well, using
    Qt Code:
    1. delete tableView;
    2. tableView = dmgr->customerTableView();
    To copy to clipboard, switch view to plain text mode 
    Ok, I rewrote the function returning the QTableWidget, it's working now.
    I forgot to pass the correct parent. *stupid*stupid*

    Soultion was
    Qt Code:
    1. QTableView *DataManager::customerTableView(QWidget* parent)
    2. {
    3. m_customerTableView = new QTableView(parent);
    4. m_customerTableView->setModel(model_customer);
    5. m_customerTableView->setObjectName(QString::fromUtf8("tableView"));
    6. m_customerTableView->setGeometry(QRect(10, 10, 701, 191));
    7. return m_customerTableView;
    8. }
    To copy to clipboard, switch view to plain text mode 
    and to call it using
    Qt Code:
    1. tableView = dmgr->customerTableView(this);
    To copy to clipboard, switch view to plain text mode 
    This is bad juju. What happens if you call "delete tableView" without the next call to "customerTableView"? What state is m_customerTableView variable left in? How about if there are other member functions of DataManager that work with m_customerTableView and what it points to is deleted outside of the DataManger class?

    A slightly better implementation than the current.
    Qt Code:
    1. QTableView * DataManager::DeleteCustomerTableView(void)
    2. {
    3. delete m_customerTableView;
    4. m_customerTableView = NULL;
    5. return m_customerTableview;
    6. }
    7. QTableView *DataManager::customerTableView(QWidget* parent)
    8. {
    9. DeleteCustomerTableView();
    10. m_customerTableView = new QTableView(parent);
    11. m_customerTableView->setModel(model_customer);
    12. m_customerTableView->setObjectName(QString::fromUtf8("tableView"));
    13. m_customerTableView->setGeometry(QRect(10, 10, 701, 191));
    14. return m_customerTableView;
    15. }
    16. ...
    17. // delete tableView; DataManager handles the delete, this call not needed.
    18. tableView = dmgr->customerTableView(this);
    To copy to clipboard, switch view to plain text mode 
    There is still a problem with the code above as it is possible to dereference a returned NULL pointer from new'd QTableView (out of memory).

    Rules for staying out of trouble when programming in C/C++.
    1) If a function returns an error code, check the returned value, never assume the function call was successful.
    2) Always check returned pointers to ensure they are not NULL, handle accordingly.
    3) If a class owns a pointer, don't delete the pointer outside of the class.
    4) If a class hands ownership of pointer to another class, apply rule 3.

    Qt's object ownership tree might blur #3 a bit. Still DataManager should handle the deletion of the object, so added DeleteCustomerTableView for this purpose.
    Qt Code:
    1. tableView = dmgr->DeleteCustomerTableView();
    To copy to clipboard, switch view to plain text mode 

    Writing defensible code is TEDIOUS WORK (actually it's second nature if you do it all time) and adds lots of extra lines of code, however the benefits are huge. When the app starts crashing during development the error will be easier to find. When the application is deployed to outside users (with varying system architecture) defensible coding will enable you to determine the problem. Defensible coding allows errors to be handled gracefully, did a new call return NULL (out of memory) then maybe some resources can be freed and new called again. Do you check the return value from QObject::connect(...), if not how do you now the connection was successful?


    Added after 9 minutes:


    Quote Originally Posted by nroberts View Post
    With class members this has some interesting and sometimes confusing implications.
    and loops.
    Qt Code:
    1. {
    2. int i = 0;
    3. .
    4. .
    5. .
    6. for(int i = 0; i < someLayout->count(); ++i) {
    7. if(someLayout->itemAt(i) == someWidget)
    8. break;
    9. }
    10. someLayout->insertWidget(i, new QWidget()); // oops, inserted widget at position 0
    11. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by pkohut; 3rd January 2011 at 20:14.

  10. The following user says thank you to pkohut for this useful post:

    homerun4711 (3rd January 2011)

  11. #9
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Default Re: How to correctly re-assign a pointer?

    Thanks for your good suggestions on writing clean code.
    I have just one more question, you wrote

    // delete tableView; DataManager handles the delete, this call not needed.
    tableView = dmgr->customerTableView(this);
    Did you mean, that DataManager automatically deletes the object created in the QtDesigner file (see code below), if tableView is assigned to another object?

    Qt Code:
    1. public:
    2. QTableView *tableView;
    3. ...
    4. void setupUi(QDialog *AddressBook)
    5. {
    6. tableView = new QTableView(AddressBook);
    7. ...
    8. }
    To copy to clipboard, switch view to plain text mode 


    Added after 25 minutes:


    Hm...I added the code you provided, now the app is crashing. The debugger says that the last call was to DeleteCustomerTableView()...
    what could be the problem?
    Last edited by homerun4711; 3rd January 2011 at 23:33.

  12. #10
    Join Date
    Dec 2010
    Location
    US, Washington State
    Posts
    54
    Thanks
    3
    Thanked 7 Times in 7 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to correctly re-assign a pointer?

    'Cause I'm still new to Qt and its object owner/memory system, I'm not exactly sure if the object should be deleted as described. Maybe deleteLater() should be called on the object, instead of delete. If that's the case then
    Qt Code:
    1. QTableView * DataManager::DeleteCustomerTableView(void)
    2. {
    3. m_customerTableView->deleteLater();
    4. m_customerTableView = NULL;
    5. return m_customerTableview;
    6. }
    To copy to clipboard, switch view to plain text mode 
    But, I'm really just guessing here.

    ps, no idea how that post ended up triple posted.


    Added after 10 minutes:


    Quote Originally Posted by homerun4711 View Post
    Hm...I added the code you provided, now the app is crashing. The debugger says that the last call was to DeleteCustomerTableView()...
    what could be the problem?
    Is m_customerTableView initialized to NULL in DataManager's constructor? If not then it is pointing to LaLa land, and the delete is blowing it up.
    Last edited by pkohut; 3rd January 2011 at 23:58.

  13. The following user says thank you to pkohut for this useful post:

    homerun4711 (4th January 2011)

  14. #11
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Default Re: How to correctly re-assign a pointer?

    Is m_customerTableView initialized to NULL in DataManager's constructor?
    You are right, extactly this was the problem. At first I initialized all tableViews with "new" objects but I changed that some hours ago and forgot to set the pointers to NULL.

  15. #12
    Join Date
    Dec 2010
    Location
    US, Washington State
    Posts
    54
    Thanks
    3
    Thanked 7 Times in 7 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to correctly re-assign a pointer?

    Quote Originally Posted by homerun4711 View Post
    You are right, extactly this was the problem. At first I initialized all tableViews with "new" objects but I changed that some hours ago and forgot to set the pointers to NULL.
    Yep, do it all the time, make some seemingly minor change and the whole thing blows up. Back to
    What works today may not work (added: in a few hours) tomorrow or next month after you've made changes to the code

  16. #13
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Default Re: How to correctly re-assign a pointer?

    you say it

  17. #14
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Default Re: How to correctly re-assign a pointer?

    Hello again!

    I encountered another problem while using the DeleteCustomerTableView() you suggested

    If I open, close and open the AddressBook again, the application crashes. The debugger
    points to DeleteCustomerTableView(). But

    If I comment the "delete m_customerTableView;" in "DeleteCustomerTableView()" everything works fine. So I think there could be a problem with a not initialized m_customerTableView. But it is set to NULL in the constructor so on the first call of AddressBook it is initialized and after that it is handled correctly, isn't it? I would be thankful if you could have another look into the code.

    Qt Code:
    1. AddressBook::AddressBook(DataManager* dmgr, QWidget *parent): QDialog(parent)
    2. {
    3. //calling this for the second time crashes the app
    4. Q_CHECK_PTR(dmgr->customerTableView());
    5. tableView = dmgr->customerTableView(this);
    6. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. DataManager::DataManager()
    2. {
    3. ...
    4. m_customerTableView = NULL; //setting to NULL in constructor
    5. ...
    6. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. QTableView *DataManager::customerTableView(QWidget* parent)
    2. {
    3. DeleteCustomerTableView();
    4.  
    5. m_customerTableView = new QTableView(parent);
    6. m_customerTableView->setModel(model_customer);
    7. return m_customerTableView;
    8. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. QTableView *DataManager::DeleteCustomerTableView()
    2. {
    3. delete m_customerTableView;
    4. m_customerTableView = NULL;
    5. return m_customerTableView;
    6. }
    To copy to clipboard, switch view to plain text mode 

  18. #15
    Join Date
    Dec 2010
    Location
    US, Washington State
    Posts
    54
    Thanks
    3
    Thanked 7 Times in 7 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to correctly re-assign a pointer?

    You've probably called delete on the tableView pointer in AddressBook's destructor. Instead call DeleteCustomerTableView().

    Also, this is no good, because an extra delete/create operation is performed.
    Qt Code:
    1. AddressBook::AddressBook(DataManager* dmgr, QWidget *parent): QDialog(parent)
    2. {
    3. //calling this for the second time crashes the app
    4. Q_CHECK_PTR(dmgr->customerTableView());
    5. tableView = dmgr->customerTableView(this);
    6. }
    To copy to clipboard, switch view to plain text mode 
    Change to -
    Qt Code:
    1. AddressBook::AddressBook(DataManager* dmgr, QWidget *parent): QDialog(parent)
    2. {
    3. tableView = dmgr->customerTableview(this);
    4. Q_ASSERT(tableView);
    5. }
    To copy to clipboard, switch view to plain text mode 

  19. #16
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: How to correctly re-assign a pointer?

    Since we are defencive programming then you should really do:
    Qt Code:
    1. AddressBook::AddressBook(DataManager* dmgr, QWidget *parent): QDialog(parent)
    2. {
    3. Q_ASSERT(dmgr);
    4. tableView = dmgr->customerTableview(this);
    5. Q_ASSERT(tableView);
    6. }
    To copy to clipboard, switch view to plain text mode 
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  20. #17
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Default Re: How to correctly re-assign a pointer?

    I haven't written a destructor. Is "delete tableView" automatically called then and thus leaving a dangling pointer which is crashing the following delete?

  21. #18
    Join Date
    Dec 2010
    Location
    US, Washington State
    Posts
    54
    Thanks
    3
    Thanked 7 Times in 7 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: How to correctly re-assign a pointer?

    Quote Originally Posted by high_flyer View Post
    Since we are defencive programming then you should really do:
    Qt Code:
    1. AddressBook::AddressBook(DataManager* dmgr, QWidget *parent): QDialog(parent)
    2. {
    3. Q_ASSERT(dmgr);
    4. tableView = dmgr->customerTableview(this);
    5. Q_ASSERT(tableView);
    6. }
    To copy to clipboard, switch view to plain text mode 
    Yep. It may seem redundant now because dmgr was/is presumably validated before calling into the function, but as the code base grows and more entry points to the function are added, doing the extra sanity checks will save your bacon down the road.

  22. #19
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: How to correctly re-assign a pointer?

    if tableViewe has a QObject parent (or aparent that takes ownership) then you don't have to worry about deleting it.
    Otherwise, you do.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  23. #20
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Default Re: How to correctly re-assign a pointer?

    Well, I am a bit confused now, because after adding a destructor

    Qt Code:
    1. AddressBook::~AddressBook()
    2. {
    3. data->DeleteCustomerTableView();
    4. }
    To copy to clipboard, switch view to plain text mode 

    everything works fine and I unterstand why this is the case:
    "delete tableView" is called automatically if there is no destructor and thus leaving a dangling pointer which is crashing the following delete in DeleteCustomerTableView()

    But also tableView has a parent (AddressBook)

    Qt Code:
    1. class Ui_AddressBook
    2. {
    3. public:
    4. QTableView *tableView;
    5. void setupUi(QDialog *AddressBook)
    6. {
    7. ...
    8. tableView = new QTableView(AddressBook);
    9. ...
    10. }
    11. }
    To copy to clipboard, switch view to plain text mode 

    and high_flyer wrote

    if tableViewe has a QObject parent (or aparent that takes ownership) then you don't have to worry about deleting it.
    so the crash should not happen at all?!?

Similar Threads

  1. Cannot assign to pixmap during painting
    By fanatos in forum Qt Programming
    Replies: 9
    Last Post: 22nd February 2016, 18:56
  2. Replies: 1
    Last Post: 4th December 2010, 18:20
  3. Assign a wchar_t array to QString
    By jacky in forum Qt Programming
    Replies: 5
    Last Post: 18th April 2009, 13:28
  4. boost::assign
    By Sivert in forum General Programming
    Replies: 0
    Last Post: 2nd May 2007, 01:23
  5. I can't assign TableView signals...
    By tomek in forum Newbie
    Replies: 5
    Last Post: 9th January 2006, 22:04

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
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.