crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

> MDI утечка памяти, Помогите разобратся с памятью...
fortero
  опции профиля:
сообщение 23.5.2011, 1:15
Сообщение #1


Участник
**

Группа: Участник
Сообщений: 132
Регистрация: 4.12.2010
Пользователь №: 2242

Спасибо сказали: 0 раз(а)




Репутация:   0  


Доброе время суток, Господа!
Вопрос у меня есть к спецам QT, я сильно начинающий, поправьте если я что-то не так понимаю или скажу.
Я пишу программу с использованием дочерних ока MDI. За основу я взял код автора книги, в посте я приведу. Но меня мучают сомнения по поводу утечки памяти! Как вообще правильно отслеживать утечку памяти когда не уверен в коде???
При помощи диспетчера задач?
Или есть более правильный метод???
Вот код, взгляните правильно он написан, память высвобождается при закрытии дочерних окон?
Там есть опция:
setAttribute(Qt::WA_DeleteOnClose);
Теоретически должно работать, но у меня есть сомнения. В этом примере дочернее окно используется для создания текстового документа. А в моём случае там ещё банда виджетов! Таблица панели управления. Но если этот код правильный, то вся банда виджетов если унаследовала от родителя то при закрытии дочернего окна они освободят память, верно?
Код:
main.cpp
#include <QApplication>
#include <QTextCodec>
#include "mainwin.h"

int main(int argc, char *argv[]){
    Q_INIT_RESOURCE(mdi);
    QApplication app(argc, argv);
    QTextCodec *codec = QTextCodec::codecForName("CP1251");
    QTextCodec::setCodecForTr(codec);
    
    MainWin mainWin;
    mainWin.show();
    return app.exec();
}


mainwin.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class QAction;
class QMenu;
class QMdiArea;
class QMdiSubWindow;
class MdiChild;
class QSignalMapper;

class MainWin : public QMainWindow {
    Q_OBJECT
public:
    MainWin();
protected:
    void closeEvent(QCloseEvent *event);
private slots:
    void newFile();
    void about();
    void updateMenus();
    void updateWindowMenu();
    MdiChild *createMdiChild();
    void setActiveSubWindow(QWidget *window);
private:
    void createActions();
    void createMenus();
    void createToolBars();
    void createStatusBar();

    MdiChild *activeMdiChild();
    QMdiSubWindow *findMdiChild(const QString &fileName);

    QMdiArea *mdiArea;
    QSignalMapper *windowMapper;

    QMenu *fileMenu;
    QMenu *windowMenu;
    QMenu *helpMenu;
    QToolBar *fileToolBar;
    QAction *newAct;
    QAction *exitAct;
    QAction *closeAct;
    QAction *closeAllAct;
    QAction *tileAct;
    QAction *cascadeAct;
    QAction *nextAct;
    QAction *previousAct;
    QAction *separatorAct;
    QAction *aboutAct;
    QAction *aboutQtAct;
};

#endif


mainwin.cpp
#include <QtGui>
#include "mainwin.h"
#include "mdichild.h"

MainWin::MainWin() {
    mdiArea = new QMdiArea;
    setCentralWidget(mdiArea);
    connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)),
            this, SLOT(updateMenus()));
    windowMapper = new QSignalMapper(this);
    connect(windowMapper, SIGNAL(mapped(QWidget *)),
            this, SLOT(setActiveSubWindow(QWidget *)));
    
    //mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    //mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    
    createActions();
    createMenus();
    createToolBars();
    createStatusBar();
    updateMenus();

    setWindowTitle(tr("MDI"));
}

void MainWin::closeEvent(QCloseEvent *event){
    mdiArea->closeAllSubWindows();
    if (activeMdiChild()) {
        event->ignore();
    } else {
        event->accept();
    }
}

void MainWin::newFile(){
    MdiChild *child = createMdiChild();
    child->newFile();
    child->show();
}

void MainWin::about(){
   QMessageBox::about(this, tr("О программе"),
            tr("Приложение <b>MDI</b>."));
}

void MainWin::updateMenus(){
    bool hasMdiChild = (activeMdiChild() != 0);
    closeAct->setEnabled(hasMdiChild);
    closeAllAct->setEnabled(hasMdiChild);
    tileAct->setEnabled(hasMdiChild);
    cascadeAct->setEnabled(hasMdiChild);
    nextAct->setEnabled(hasMdiChild);
    previousAct->setEnabled(hasMdiChild);
    separatorAct->setVisible(hasMdiChild);
}

void MainWin::updateWindowMenu(){
    windowMenu->clear();
    windowMenu->addAction(closeAct);
    windowMenu->addAction(closeAllAct);
    windowMenu->addSeparator();
    windowMenu->addAction(tileAct);
    windowMenu->addAction(cascadeAct);
    windowMenu->addSeparator();
    windowMenu->addAction(nextAct);
    windowMenu->addAction(previousAct);
    windowMenu->addAction(separatorAct);

    QList<QMdiSubWindow *> windows = mdiArea->subWindowList();
    separatorAct->setVisible(!windows.isEmpty());

    for (int i = 0; i < windows.size(); ++i) {
        MdiChild *child = qobject_cast<MdiChild *>(windows.at(i)->widget());

        QString text;
        if (i < 9) {
            text = tr("&%1 %2").arg(i + 1)
                               .arg(child->userFriendlyCurrentFile());
        } else {
            text = tr("%1 %2").arg(i + 1)
                              .arg(child->userFriendlyCurrentFile());
        }
        QAction *action  = windowMenu->addAction(text);
        action->setCheckable(true);
        action ->setChecked(child == activeMdiChild());
        connect(action, SIGNAL(triggered()), windowMapper, SLOT(map()));
        windowMapper->setMapping(action, windows.at(i));
    }
}

MdiChild *MainWin::createMdiChild(){
    MdiChild *child = new MdiChild;
    mdiArea->addSubWindow(child);

    return child;
}

void MainWin::createActions(){
    newAct = new QAction(QIcon(":/images/filenew.png"), tr("&Новый"), this);
    newAct->setShortcut(tr("Ctrl+N"));
    newAct->setStatusTip(tr("Создать новое окно"));
    connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));

    exitAct = new QAction(QIcon(":/images/fileexit.png"), tr("В&ыход"), this);
    exitAct->setShortcut(tr("Ctrl+Q"));
    exitAct->setStatusTip(tr("Завершить приложение"));
    connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));

    closeAct = new QAction(tr("&Закрыть"), this);
    closeAct->setShortcut(tr("Ctrl+F4"));
    closeAct->setStatusTip(tr("Заркыть текущее окно"));
    connect(closeAct, SIGNAL(triggered()),
            mdiArea, SLOT(closeActiveSubWindow()));

    closeAllAct = new QAction(tr("Закрыть &все"), this);
    closeAllAct->setStatusTip(tr("Закрыть все окна"));
    connect(closeAllAct, SIGNAL(triggered()),
            mdiArea, SLOT(closeAllSubWindows()));

    tileAct = new QAction(tr("&Черепица"), this);
    tileAct->setStatusTip(tr("Расположить окна рядом"));
    connect(tileAct, SIGNAL(triggered()), mdiArea, SLOT(tileSubWindows()));

    cascadeAct = new QAction(tr("&Каскад"), this);
    cascadeAct->setStatusTip(tr("Расположить окна каскадом"));
    connect(cascadeAct, SIGNAL(triggered()), mdiArea, SLOT(cascadeSubWindows()));

    nextAct = new QAction(tr("&Следующее"), this);
    nextAct->setStatusTip(tr("Перейти к следующему окну"));
    connect(nextAct, SIGNAL(triggered()),
            mdiArea, SLOT(activateNextSubWindow()));

    previousAct = new QAction(tr("&Предыдущее"), this);
    previousAct->setStatusTip(tr("Перейти к предыдущему окну"));
    connect(previousAct, SIGNAL(triggered()),
            mdiArea, SLOT(activatePreviousSubWindow()));

    separatorAct = new QAction(this);
    separatorAct->setSeparator(true);

    aboutAct = new QAction(tr("&О программе"), this);
    aboutAct->setStatusTip(tr("Показать информацию о программе"));
    connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));

    aboutQtAct = new QAction(tr("О библиотеке &Qt"), this);
    aboutQtAct->setStatusTip(tr("Показать информацию о библиотеке Qt"));
    connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
}

void MainWin::createMenus(){
    fileMenu = menuBar()->addMenu(tr("&Файл"));
    fileMenu->addAction(newAct);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAct);

    windowMenu = menuBar()->addMenu(tr("&Окно"));
    updateWindowMenu();
    connect(windowMenu, SIGNAL(aboutToShow()), this, SLOT(updateWindowMenu()));

    menuBar()->addSeparator();

    helpMenu = menuBar()->addMenu(tr("&Справка"));
    helpMenu->addAction(aboutAct);
    helpMenu->addAction(aboutQtAct);
}

void MainWin::createToolBars(){
    fileToolBar = addToolBar(tr("Файл"));
    fileToolBar->addAction(newAct);
    fileToolBar->addSeparator();
    fileToolBar->addAction(exitAct);
}

void MainWin::createStatusBar(){
    statusBar()->showMessage(tr("Готов"));
}

MdiChild *MainWin::activeMdiChild(){
    if (QMdiSubWindow *activeSubWindow = mdiArea->activeSubWindow())
        return qobject_cast<MdiChild *>(activeSubWindow->widget());
    return 0;
}

QMdiSubWindow *MainWin::findMdiChild(const QString &fileName){
    QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath();

    foreach (QMdiSubWindow *window, mdiArea->subWindowList()) {
        MdiChild *mdiChild = qobject_cast<MdiChild *>(window->widget());
        if (mdiChild->currentFile() == canonicalFilePath)
            return window;
    }
    return 0;
}

void MainWin::setActiveSubWindow(QWidget *window){
    if (!window)
        return;
    mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(window));
}


mdichild.h
#ifndef MDICHILD_H
#define MDICHILD_H

#include <QTextEdit>

class MdiChild : public QTextEdit {
    Q_OBJECT
public:
    MdiChild();
    void newFile();
    QString userFriendlyCurrentFile();
    QString currentFile() { return curFile; }
private:
    void setCurrentFile(const QString &fileName);
    QString strippedName(const QString &fullFileName);
    QString curFile;
    bool isUntitled;
};

#endif


mdichild.cpp
#include <QtGui>
#include "mdichild.h"

MdiChild::MdiChild(){
    setAttribute(Qt::WA_DeleteOnClose);
    isUntitled = true;
}

void MdiChild::newFile(){
    static int sequenceNumber = 1;

    isUntitled = true;
    curFile = tr("document%1.txt").arg(sequenceNumber++);
    setWindowTitle(curFile + "[*]");
}

QString MdiChild::userFriendlyCurrentFile(){
    return strippedName(curFile);
}

void MdiChild::setCurrentFile(const QString &fileName){
    curFile = QFileInfo(fileName).canonicalFilePath();
    isUntitled = false;
    document()->setModified(false);
    setWindowModified(false);
    setWindowTitle(userFriendlyCurrentFile() + "[*]");
}

QString MdiChild::strippedName(const QString &fullFileName){
    return QFileInfo(fullFileName).fileName();
}


Очень надеюсь на Вашу помощь, для меня сейчас этот вопрос "вопрос жизни и смерти"!
Спасибо за внимание!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
 
Начать новую тему
Ответов
Litkevich Yuriy
  опции профиля:
сообщение 23.5.2011, 7:43
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(fortero @ 23.5.2011, 4:15) *
При помощи диспетчера задач?
Или есть более правильный метод???
ни в коем случае. Диспетчер задач вообще не позволяет этого делать. Под виндовозом не знаю что посоветовать, скорее всего все инструменты будут платные. Можно этот же код тестировать под линём, под него есть хороший инструмент - valgrind
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Сообщений в этой теме


Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 22.12.2024, 15:10