[SOLVED] memory deallocation,is there a nicer way to do that?



  • Hello,

    I have a pointer and i want to be deleted after the scope runs out,so I use the QScopedPointer.
    The point is that this doesn't work.(I understand why it doesn't).

    @QScopedPointer<const char*> key = static_cast<const char *> something()@

    so in order to delete the pointer i did this

    @delete key@

    Is there a nicer way to do this???

    thanks in advance


  • Moderators

    Yes, nothing !!

    the documentation sais in the first line:
    [quote]The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon destruction.[/quote]

    [edit] Sorry, hit the wrong button.

    It is sort of a shared pointer (see [[doc:QSharedPointer]]).



  • After the scope runs out QScopedPointer call destructor him self, so you don't need to call
    @delete key;@
    As koahnig says you should put to QScopedPointer dynamically allocated object, so
    @SomeClass * something() { return new SomeClass(); }@
    @QScopedPointer<SomeClass> key(something());@



  • Just forget, QScopedPointer is a template class so you need declare just type and this type will be a pointer inside class. In your case obtained QScopedPointer and type is: @const char **.@
    Sorry for my english :-)



  • First of all,thank you for answers.

    Yes you have right.
    @const char something; @

    is not an object.

    The point is that i can't do

    @delete key@

    because in the last line of my scope the value of key is being returned.

    @return key;@

    Do you have any idea how i can delete the key?



  • Can you give us more code? Where you want delete and what key, write all algo



  • here,

    @QVariant Something() {
    const char* key = m_topEntries.at(parent.row());
    return key;
    }@

    I want to delete the key,eg

    @delete key;@

    but how can i do it when i need it in the last line of my scope?



  • If you have there @const char* key = m_topEntries.at(parent.row());@ a dynamically allocated object so for example you can do like this:
    @
    QVariant Something() {
    const char* key = m_topEntries.at(parent.row());
    return qVariantFromValue(QByteArray(key));
    }

    QVariant variant(Something());
    if (variant.type() == QVariant::ByteArray) {
    QByteArray byteArray(variant.toByteArray());
    //do something

    //and at the and
    delete byteArray().data();
    }
    @



  • More elegantly you can do like this:
    register sharedPointer somewhere
    @
    Q_DECLARE_METATYPE(QSharedPointer<const char>);
    @
    then
    @
    QVariant Something() {
    QSharedPointer<const char> keyPointer(m_topEntries.at(parent.row()));
    return QVariant().setValue(key));
    }

    QVariant variant(Something());
    if (variant.canConvert<QSharedPointer<const char> >()) {
    QSharedPointer<const char> keyPointer(variant.value<QSharedPointer<const char> >());
    //do something
    }
    @
    So when variant goes out if scope it's automaticly delete your key.
    Try it I don't test this.



  • A few annotations:

    • m_topEntries.at(...) does obviously return a pointer to an already existing object and does not allocate any new memory. There is no need to call delete key unless you want to delete the object the pointer does point to (key is created on the stack and does automatically vanish after it goes out of scope).
    • If so, you should use takeAt() instead of at() or at least reset the item to null after you have deleted the object otherwise your container will contain a dangling pointer.
    • I assume that the objects stored within the m_topEntries container are created with new, otherwise you must not call delete.
    • QScopedPointer is not the object itself - it is a pointer to an object. It automatically destroys (read, calls delete) the object it points to at the time QScopedPointer itself is destroy (for example when created on the stack and going out of scope).
    • QScopedPointer wraps a pointer for the given type, thus it has to read QScopedPointer<const char> instead of QScopedPointer<const char*>.
    • When using a QScopedPointer to delete the object make sure that the object is removed from the container as well (see #2).
    • If it is about storing strings you should go for QString instead of const char*. QString supports unicode and is implicitly shared, which means that it is automatically destroyed as soon as not referenced anymore.


  • [quote author="Lukas Geyer" date="1313262099"]A few annotations:

    • m_topEntries.at(...) does obviously return a pointer to an already existing object and does not allocate any new memory. There is no need to call delete key unless you want to delete the object the pointer does point to (key is created on the stack and does automatically vanish after it goes out of scope).
    • If so, you should use takeAt() instead of at() or at least reset the item to null after you have deleted the object otherwise your container will contain a dangling pointer.
    • I assume that the objects stored within the m_topEntries container are created with new, otherwise you must not call delete.
    • QScopedPointer is not the object itself - it is a pointer to an object. It automatically destroys (read, calls delete) the object it points to at the time QScopedPointer itself is destroy (for example when created on the stack and going out of scope).
    • QScopedPointer wraps a pointer for the given type, thus it has to read QScopedPointer<const char> instead of QScopedPointer<const char*>.
    • When using a QScopedPointer to delete the object make sure that the object is removed from the container as well (see #2).
    • If it is about storing strings you should go for QString instead of const char*. QString supports unicode and is implicitly shared, which means that it is automatically destroyed as soon as not referenced anymore.[/quote]
      Lukas you are the man :-) with my English I've afraid wrote such explanation.


  • [quote author="Lukas Geyer" date="1313262099"]A few annotations:

    • m_topEntries.at(...) does obviously return a pointer to an already existing object and does not allocate any new memory. [/quote]

    correct :)

    [quote](key is created on the stack and does automatically vanish after it goes out of scope).[/quote]

    I understand that everything that is allocated in the stack that is being deleted automatically when it goes out of scope.
    But why const char* is allocated in stack and not in the heap?
    Pointer are allocated on the heap.But not this one.It has to do something with the arrays but i don't understand what.

    [quote]* If it is about storing strings you should go for QString instead of const char*. QString supports unicode and is implicitly shared, which means that it is automatically destroyed as soon as not referenced anymore.[/quote]

    This is a whole different story.
    I am using the libs of an open source project,which is using the const char* instead of QString.Personally like you i prefer the QString.

    thank you for your help!



  • [quote author="Giorgos Tsiapaliwkas" date="1313297784"][quote author="Lukas Geyer" date="1313262099"](key is created on the stack and does automatically vanish after it goes out of scope).[/quote]
    I understand that everything that is allocated in the stack that is being deleted automatically when it goes out of scope.
    But why const char* is allocated in stack and not in the heap?
    Pointer are allocated on the heap. But not this one.It has to do something with the arrays but i don't understand what.[/quote]

    No. A pointer and the object it points to are two different things. Both may exist on the stack or on the heap. A pointer is usually a variable on the stack pointing to an object on the heap (or the stack).

    As a rule of thumb every single variable (including pointers) exists on the stack except those beeing on the right side of new. Only those created on the heap must be deleted using delete - those on the stack must not be deleted!

    @
    void foobar()
    {
    int intVariable = 0; // variable of type "int" created on the stack named "intVariable"
    float floatVariable = 0; // variable of type "float" created on the stack named "floatVariable"

    int* intPointer = 0;                    // variable of type "pointer to int" created on the stack (not heap) named "intPointer"
    float* floatPointer = &floatVariable;   // variable of type "pointer to float" created on the stack (not heap) named "floatPointer"
                                            // pointing to an object on the stack (not heap)
    
    QObject* objectPointer = new QObject;   // there are two things created here:
                                            // - a variable of type "pointer to QObject" created on the stack pointing to an object on the heap 
                                            // - an object of type QObject created on the heap  
    
    QObject* anotherPointer = objectPointer;   // variable of type "pointer to QObject" created on the stack pointing to the same object on the heap as "objectPointer" does named "anotherPointer"
                                               // there is no (!) object on the heap created here
    
    // when leaving the function now, all of the six variables created on the stack will go out of scope
    // but the object on the heap persists
    
    delete objectPointer;   // the object objectPointer points to is deleted from heap, but the pointer to it "objectPointer" still exists on the stack
                            // "objectPointer" and "anotherPointer" are now both invalid, because they point to a location in memory where no object exists
    

    }
    @

    [quote author="Giorgos Tsiapaliwkas" date="1313297784"]I am using the libs of an open source project,which is using the const char* instead of QString.Personally like you i prefer the QString.

    thank you for your help![/quote]

    QString can be used to encapsulate plain old char* strings. Just take a look at "QString":http://doc.qt.nokia.com/latest/qstring.html.



  • [quote author="Lukas Geyer" date="1313317669"]
    QString can be used to encapsulate plain old char* strings. Just take a look at "QString":http://doc.qt.nokia.com/latest/qstring.html.[/quote]

    Not really, QString always is unicode, never ASCII. If you want to encapsulate char* use QLatin1String.



  • [quote author="Lukas Geyer" date="1313317669"][quote author="Giorgos Tsiapaliwkas"
    @
    void foobar()
    {
    int intVariable = 0; // variable of type "int" created on the stack named "intVariable"
    float floatVariable = 0; // variable of type "float" created on the stack named "floatVariable"

    int* intPointer = 0;                    // variable of type "pointer to int" created on the stack (not heap) named "intPointer"
    float* floatPointer = &floatVariable;   // variable of type "pointer to float" created on the stack (not heap) named "floatPointer"
                                            // pointing to an object on the stack (not heap)
    
    QObject* objectPointer = new QObject;   // there are two things created here:
                                            // - a variable of type "pointer to QObject" created on the stack pointing to an object on the heap 
                                            // - an object of type QObject created on the heap  
    
    QObject* anotherPointer = objectPointer;   // variable of type "pointer to QObject" created on the stack pointing to the same object on the heap as "objectPointer" does named "anotherPointer"
                                               // there is no (!) object on the heap created here
    
    // when leaving the function now, all of the six variables created on the stack will go out of scope
    // but the object on the heap persists
    
    delete objectPointer;   // the object objectPointer points to is deleted from heap, but the pointer to it "objectPointer" still exists on the stack
                            // "objectPointer" and "anotherPointer" are now both invalid, because they point to a location in memory where no object exists
    

    }
    @
    [/quote]

    This one gives the answer to my question!

    Thanks a lot :)

    So when one pointer is not being followed by the new keyword,then there is no need to use the delete keyword.Correct?

    P.S.:sorry for my late resonse but here (in my country) we had a big celebration and i was away from my pc.



  • [quote author="Giorgos Tsiapaliwkas" date="1313517268"]
    So when one pointer is not being followed by the new keyword,then there is no need to use the delete keyword. Correct?[/quote]

    Short answer. Yes.

    Long answer. Basically every single variable is created on the stack, besides those explicitly created on the heap using the new keyword. Only those created on the heap must be explicitly deleted using delete (everything else must not be deleted). When using new, only the object on the right side of new is created on the heap.

    new and delete can be seen as ordinary functions, which just reserve a free block of memory. To access this block of memory one has to know where in memory this block has been reserved. And this is what the new "function" returns - the address of the block of memory it has just reserved. This return value is usually stored in a local variable (created on the stack) called a pointer.

    Pointers are an incredible powerful feature of the C / C++ languages, although they are sometimes a bit hard to understand. One essential thing to understand is that the pointer itself and the bit of memory it points to are two different things.

    Fundamental knowledge of how computers work (and how memory does work) is a good start if one wants to understand how pointers work. Fortunately "Google":http://www.google.com/search?q=c+++pointers has tons of answers on that.



  • After a little googling i found that if inside in a method there is
    @something* foo() {
    return new something;}@

    and then if i do

    @something *a = foo();@

    that i have to use the delete keyword,

    @delete a;@

    So,in this situation

    @class SidebarTableWidget : public QTableWidget
    {
    Q_OBJECT

    public:
    SidebarTableWidget(Qt::DockWidgetArea location, QWidget *parent = 0);
    ~SidebarTableWidget();
    QScrollBar *m_horizontalSB;
    };
    SidebarTableWidget::SidebarTableWidget(Qt::DockWidgetArea location, QWidget *parent){
    m_horizontalSB = horizontalScrollBar();
    //m_horizontalSB doesn't create a memleak.Correct?
    }@

    I guess that Qt handles this and it doesn't create a mem leak.correct?



  • [quote author="Giorgos Tsiapaliwkas" date="1313574152"]
    I guess that Qt handles this and it doesn't create a mem leak.correct?
    [/quote]
    Yes it's "correct":http://doc.qt.nokia.com/latest/qobject.html#QObject if you give parent to widget



  • [quote author="rokemoon" date="1313574984"]
    if you give parent to widget
    [/quote]

    Do you mean this?

    @SidebarTableWidget *a = new SidebarTableWidget(this);@



  • There are multiple ways how an object can become the parent of another. Passing a parent object to a constructor of another object is one of it, yes.



  • [quote author="Giorgos Tsiapaliwkas" date="1313575590"][quote author="rokemoon" date="1313574984"]
    if you give parent to widget
    [/quote]

    Do you mean this?

    @SidebarTableWidget *a = new SidebarTableWidget(this);@
    [/quote]
    yes, like this



  • thank you.

    You explained all my questions.

    I will make the thread solved



  • [quote author="Giorgos Tsiapaliwkas" date="1313581676"]thank you.

    You explained all my questions.

    I will make the thread solved[/quote]
    Glad to hear it:-)



  • [quote author="Lukas Geyer" date="1313317669"][quote author="Giorgos Tsiapaliwkas" date="1313297784"][quote author="Lukas Geyer" date="1313262099"](key is created on the stack and does automatically vanish after it goes out of scope).[/quote]
    I understand that everything that is allocated in the stack that is being deleted automatically when it goes out of scope.
    But why const char* is allocated in stack and not in the heap?
    Pointer are allocated on the heap. But not this one.It has to do something with the arrays but i don't understand what.[/quote]

    No. A pointer and the object it points to are two different things. Both may exist on the stack or on the heap. A pointer is usually a variable on the stack pointing to an object on the heap (or the stack).

    As a rule of thumb every single variable (including pointers) exists on the stack except those beeing on the right side of new. Only those created on the heap must be deleted using delete - those on the stack must not be deleted!

    @
    void foobar()
    {
    int intVariable = 0; // variable of type "int" created on the stack named "intVariable"
    float floatVariable = 0; // variable of type "float" created on the stack named "floatVariable"

    int* intPointer = 0;                    // variable of type "pointer to int" created on the stack (not heap) named "intPointer"
    float* floatPointer = &floatVariable;   // variable of type "pointer to float" created on the stack (not heap) named "floatPointer"
                                            // pointing to an object on the stack (not heap)
    
    QObject* objectPointer = new QObject;   // there are two things created here:
                                            // - a variable of type "pointer to QObject" created on the stack pointing to an object on the heap 
                                            // - an object of type QObject created on the heap  
    
    QObject* anotherPointer = objectPointer;   // variable of type "pointer to QObject" created on the stack pointing to the same object on the heap as "objectPointer" does named "anotherPointer"
                                               // there is no (!) object on the heap created here
    
    // when leaving the function now, all of the six variables created on the stack will go out of scope
    // but the object on the heap persists
    
    delete objectPointer;   // the object objectPointer points to is deleted from heap, but the pointer to it "objectPointer" still exists on the stack
                            // "objectPointer" and "anotherPointer" are now both invalid, because they point to a location in memory where no object exists
    

    }
    @
    [/quote]

    Can I also use

    @delete anotherPointer;@

    And the pointer "objectPointer" on heap will delete?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.