Версия для печати темы
Форум на CrossPlatform.RU _ Qt GUI _ Утечка памяти QTextEdit
Автор: Anticross 6.8.2010, 12:17
При добавлении каждой последующей строки в QTextEdit съедается оперативная память. Дело в том что я использую виджет в качестве лога программы и туда добавляются записи чуть ли не каждую секунду. Была идея организовать вывод таким образом:
1) выводить в виджет определенное количество строк
2) При привышении лимита сохранять содержимое виджета в файл и очищать содержимое виджета
3) При прокрутке вверх либо вниз подгружать соответсвующий файл в виджет.
Может кто знает более простой(или правильный) способ. Подскажите пожалуйста.
Автор: Алексей1153 6.8.2010, 12:28
Цитата(Anticross @ 6.8.2010, 15:17)

Может кто знает более простой(или правильный) способ. Подскажите пожалуйста
легко
Но сначала скажи - тебе нужно деление на строки или один сплошной текст с \r\n сойдёт ?
Автор: BRE 6.8.2010, 12:29
Посмотри еще это: http://www.prog.org.ru/topic_14489_0.html
Автор: Алексей1153 6.8.2010, 12:43
в любом случае, основная идкя - хранить данные в контейнере, там же и обрезать старые данные. А в виджет выводить не чаще, скажем, чем раз в секунду, выводя из контейнера текущие данные (а если не менялись - то и не выводить снова).
А ещё вопрос на засыпку - покажи ка код добавления строки, уж не из-за new QString без delete у тебя утечка ?
Автор: Anticross 6.8.2010, 13:01
LogWidget.h
CODE
#ifndef _LOGWIDGET_H_
#define _LOGWIDGET_H_
#include <QTextEdit>
class LogWidget : public QTextEdit {
//--------------------------------------------------------------------------------------------------
public: void error(const QString & msg) {
setTextColor (WARNING_TEXT_COLOR);
setFontWeight(QFont::Bold);
append(QString("%1 : %2").arg(QTime::currentTime().toString("hh:mm:ss")).arg(msg));
}
//--------------------------------------------------------------------------------------------------
public: void warning(const QString & msg) {
setTextColor (WARNING_TEXT_COLOR);
setFontWeight(QFont::Normal);
append(QString("%1 : %2").arg(QTime::currentTime().toString("hh:mm:ss")).arg(msg));
}
//--------------------------------------------------------------------------------------------------
public: void message(const QString & msg) {
setTextColor (Qt::blue);
setFontWeight(QFont::Normal);
append(QString("%1 : %2").arg(QTime::currentTime().toString("hh:mm:ss")).arg(msg));
}
//--------------------------------------------------------------------------------------------------
public: void debug (const QString & msg) {
setTextColor (Qt::black);
setFontWeight(QFont::Normal);
append(QString("%1 : %2").arg(QTime::currentTime().toString("hh:mm:ss")).arg(msg));
}
//--------------------------------------------------------------------------------------------------
};
#endif//_LOGWIDGET_H_
Log.h
CODE
#ifndef LOG_H
#define LOG_H
#include <QMutex>
#define LOG_DEBUG Log::debug
#define LOG_MESSAGE Log::message
#define LOG_WARNING Log::warning
#define LOG_ERROR Log::error
class LogWidget;
QT_BEGIN_NAMESPACE
class QString;
QT_END_NAMESPACE
class Log {
//--------------------------------------------------------------------------------------------------
private: static LogWidget * m_log;
private: static QMutex m_mutex;
//--------------------------------------------------------------------------------------------------
public: static void setLogWidget(LogWidget * wnd);
//--------------------------------------------------------------------------------------------------
public: static void error (const QString & msg);
public: static void warning(const QString & msg);
public: static void message(const QString & msg);
public: static void debug (const QString & msg);
//--------------------------------------------------------------------------------------------------
};
#endif//LOG_H
Log.cpp
CODE
#include "StdAfx.h"
LogWidget * Log::m_log = NULL;
QMutex Log::m_mutex;
//--------------------------------------------------------------------------------------------------
void Log::setLogWidget(LogWidget * log) {
QMutexLocker locker(&m_mutex);
m_log = log;
}
//--------------------------------------------------------------------------------------------------
void Log::error(const QString & msg) {
QMutexLocker locker(&m_mutex);
if (m_log == NULL)
qWarning(msg.toAscii());
else
m_log->error(msg);
}
//--------------------------------------------------------------------------------------------------
void Log::warning(const QString & msg) {
QMutexLocker locker(&m_mutex);
if (m_log == NULL)
qWarning(msg.toAscii());
else
m_log->warning(msg);
}
//--------------------------------------------------------------------------------------------------
void Log::message(const QString & msg) {
QMutexLocker locker(&m_mutex);
if (m_log == NULL)
qWarning(msg.toAscii());
else
m_log->message(msg);
}
//--------------------------------------------------------------------------------------------------
void Log::debug(const QString & msg) {
QMutexLocker locker(&m_mutex);
if (m_log == NULL)
qDebug(msg.toAscii());
else
m_log->debug(msg);
}
//--------------------------------------------------------------------------------------------------
Автор: Алексей1153 6.8.2010, 13:10
Хорошо, покажи пример того, как ты снаружи класса вызываешь метод
Log::message(const QString & msg)
- как готовишь для него строку ?
Автор: Anticross 6.8.2010, 13:13
Посмотри еще это: http://www.prog.org.ru/topic_14489_0.html
Небольшой сложностью по сравнению с этим решением есть то что пользователю должен быть доступен весь текст. По этому если лишь ограничить блок выводимых данных старый текст утеряется, что непозволительно в моем случае.
Автор: Алексей1153 6.8.2010, 13:17
Anticross, я смотрел. По твоим словам у тебя - лог сообщений, а это никак не хранение в контроле, это по меньшей мере
std::vector<QString*>
или
QList<QString*>
а ещё лучше - кеш (в STL нету, я себе сам писал)
насчёт того кода тебя пыатю - подоздеваю, что ты делаешь как-то так:
myLog->message(new QString("12345"));
отсюда может быть утечка. А иначе - это не утечка вовсе, а просто память то занимается потихоньку не удаляемыми данными
Автор: Anticross 6.8.2010, 13:20
Собственно говоря вот :
LOG_MESSAGE("Some text or QString here");
Автор: Алексей1153 6.8.2010, 13:25
Понятно. Остаётся
Цитата(Алексей1153 @ 6.8.2010, 16:17)

А иначе - это не утечка вовсе, а просто память то занимается потихоньку не удаляемыми данными
Автор: Anticross 6.8.2010, 13:33
Цитата(Алексей1153 @ 6.8.2010, 16:17)

А иначе - это не утечка вовсе, а просто память то занимается потихоньку не удаляемыми данными
Все правильно, в этом то и состоит задача: хранить все сообщения на ЖД а выводить в виджет лишь актуальную в данный момент. Причем визуально пользователь не должен ощутить никакой разницы(тобиш пролистывать как будто текст целяком хранится в виджете). И еще вопрос: Освободится ли выделенная память после удаления текста из виджета скажем путем выделения строк и нажатия del ?
Автор: Алексей1153 6.8.2010, 13:41
Anticross, да не думай, что там в виджете будет. Полагаю, что такое действие как "выделения строк и нажатия del" вообще нельзя допускать )
Лучше применить табличный виджет и сделать на нём фиксированное число строк - ровно сколько влазит на экран. Сообщения же пусть лежат в кеше (если своего нет, могу код скинуть, только там с MFC немного переделать придётся на Qt). И вот, пользователь будет двигать ползунок, а ты будешь двигать воображаемое окно, и оттуда отображать текущие строки. Будет быстро, красиво и монолитно )) Но сами сообщения надо будет в БД хранить (или в аналоге)
Автор: BRE 6.8.2010, 13:59
Anticross если логи не обязательно выводить в QTextEdit, то использование QListView/QTableView и своей модели будет лучшим решением.
Автор: kuzulis 6.8.2010, 14:09
Anticross,
лог пиши постоянно в файл. А в TextEdit выводи только несколько текущих строк... Например ограничься 50-ю строками.
т.е. при перемещении вертикального скроллбара ты просто подгружай из лог-файла нужные данные и отображай их в TextEdit.
Одновременно при добавлении новой записи в лог-файл ты отображай её в TextEdit.
Типа в данном случае TextEdit выступает как интерактивная гляделка лог-файла.
--
Упс.. это таже идея что и в "Сообщение #11"
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)