Странное поведение в программе Qt при игре с деструкторами - PullRequest
2 голосов
/ 20 марта 2012

Я недавно начал изучать qt и играл с ним, также помня немного о c ++, так как некоторое время не использовал его ...

В любом случае, я сделал этот простой тестовый класс, чтобы посмотреть, что произойдет, если у вас есть свисающий указатель:

#include <QtCore/QCoreApplication>

#include <iostream>

class Test{
public:
    QString str;
    int i;
public:
    Test(){
        i=1337;
        str="str";
        std::cout<<"initialized\n";
    }

    ~Test(){
        std::cout<<"destructor called\n";
        delete &str;
        delete &i;
        /*the program MAY run if the deletes aren't called;*/
    }
};

Test* p;

void test_function(){
    Test a;
    p=&a; //this will give a segfault, since the destructor of a is called at the end of this function's scope, but p still points to a
    //p=new Test(a); //this will call the copy constructor of p, copying the values from a to p
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    test_function();

    std::cout<<p->str.toStdString() << p->i<<std::endl;

    return a.exec();
}

, который, конечно же, дает сбой (но он не говорит почему - вероятно, segfault). Однако, если я прокомментирую строку, где вызывается висячий указатель (cout в main ()), программа сейчас вылетает, выдавая исключение «std :: bad_alloc». Следующий список проверенных независимо друг от друга причин, по которым исключение больше не вызывается:

  • комментирование инициализации str;
  • комментируя деструктор str;
  • замена QString на std :: string;

То, что я пробовал и не имело никакого эффекта, это инициализация str с помощью QString :: fromStdString ("str") (вместо просто "str").

Я также пытался окружить инициализацию и уничтожение str (в то время как QString) блоком try / catch, но безрезультатно. Кроме того, попробуйте / поймать для test_function () - безрезультатно. Однако мне удалось поймать исключение, окружив a.exec () в блоке try / catch.

Почему выдается исключение при комментировании команды, но в противном случае происходит сбой? Почему инициализация и деструктор для str генерируют исключение, но комментирование одного или обоих приводит к сбою? (теперь, когда я пишу это, я понимаю, что это может быть единственной проблемой; однако, почему происходит сбой для QString, а не для std :: string?) Почему a.exec () вызывает исключение?

Может ли кто-нибудь, кто знает qt (или даже c ++) - лучше меня, - объяснить, что происходит? Спасибо

Ответы [ 2 ]

4 голосов
/ 20 марта 2012

Это одна ошибка:

delete &str;
delete &i;

пытается delete переменные, которые не были динамически распределены, т.е. с использованием new.Удалить эти две строки.i и str будут уничтожены автоматически при уничтожении экземпляра Test.

1 голос
/ 20 марта 2012

Я не совсем уверен, какой ответ вы ищете, но даже если вы не используете висячий указатель p, вы повредили кучу (или какое-либо другое неопределенное поведение), потому что в вашемdtor для Test у вас есть следующее:

~Test(){
    std::cout<<"destructor called\n";
    delete &str;
    delete &i;
    /*the program MAY run if the deletes aren't called;*/
}

Два оператора delete удаляют вещи, которые не выделены через new - не делайте этого.

...