Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [QT] Почему нельзя удалить объект в слоте? Хочу удалить QSocket из своего слота 
V
    Опции темы
null56
Дата 18.12.2008, 11:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



Ну собственно вопрос стоит так:
1) связываю сигнал от объекта с обработчиком
2) в случае неудачи вызывается соответствующий слот
3) хочу удалить вызывающий объект из этого слота...

Ругается и если delete ((SslSocket *)sender()) и если удаляю сохранненый указатель на этот объект
Как можно удалить объект из слота, который он вызвал? 

Добавлю лишь:
1) что этот слот связан с несколькими сигналами
2) объект создается динамически

Заранее благодарен

Добавлено через 6 минут и 4 секунды
хотя sender()->deleteLater() помог... Это корректно? он динамический объект точно удалил, я это проверил в деструкторе этого объекта?
PM MAIL   Вверх
SABROG
Дата 18.12.2008, 11:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Да deleteLater() хороший вариант, т.к. объект удалится после возвращения в eventloop. И его можно вызывать многократно безопасно, например, если на один слот приходит несколько сигналов. Тролли честно предупреждают, что при использовании sender() надо быть осторожным с удалением объекта если к одному слоту подключено несколько сигналов, а также о том, что указатель, который возвращает sender не одно и то же, что и this. Т.е. при каждом попадании в слот указатель возвращаемый sender'ом может быть разным и валидным только пока слот выполняется, пока объект существует и пока сигнал законнекчен к слоту. Но это, если я правильно все понял.


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
null56
Дата 18.12.2008, 12:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



Просто вот чего я пытаюсь сделать....

Код

...
connect(p_new_client_connection, SIGNAL(encrypted()), this, SLOT(ready()));
connect(p_new_client_connection, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(fail()));
connect(p_new_client_connection, SIGNAL(stateChanged (QAbstractSocket::SocketState)), this, SLOT(fail()));
sleep(5);
qDebug("Start encryption");
p_new_client_connection->startEncrypt(mSslCertificate, mSslKey);
...


Далее функции обработки

ready()
Код

void SslServer :: ready()            /*private slot*/
{
    qDebug("success");
    qDebug("Emited socket descriptor: %d", ((SslSocket *)sender())->socketDescriptor());
    qDebug("Mode: %d", ((SslSocket *)sender())->mode());
    qDebug("State: %d", ((SslSocket *)sender())->state());
}


И функция изменения состояния:
Код

void SslServer :: fail()            /*private slot*/
{
    const SslSocket * p_sender_socket = (SslSocket *)sender();
    qDebug("Fail");
    qDebug("Emited socket descriptor: %d", p_sender_socket->socketDescriptor());
    qDebug("Mode: %d", p_sender_socket->mode());
    qDebug("State: %d", p_sender_socket->state());
    QList<QSslError> list_errors;
    list_errors = p_sender_socket->sslErrors();
    qDebug("errors count: %d", list_errors.count());
    sender()->deleteLater();
}


После создания нового подключения, я соединяю сигналами с нужными слотами в таймауте рву соединение со стороны клиента и запускаю startServerEnclytion... Получается, что объект не удалится, пока не отработают все его сигналы, потому что вывод в консоль показывает, дважды вызов на событие stateChange()

Вывод в консоль
Код

new connection
Start encryption

Fail
Emited socket descriptor: 10
Mode: 2
State: 6
errors count: 0

Fail
Emited socket descriptor: 10
Mode: 2
State: 0
errors count: 0
DESTROY    !!!! ЭТО ВЫЗЫВАЕТСЯ В ДЕСТРУКТОРЕ ОБЪЕКТА SslSocket


PM MAIL   Вверх
SABROG
Дата 18.12.2008, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Первый раз приходит QAbstractSocket::ClosingState, типа дожидаемся завершения получения данных, если такие есть и закрываемся. Второй раз приходит QAbstractSocket::UnconnectedState, типа закрылись.

Думается мне что все-таки придется делать два слота и прописать в них соотв. параметры, чтобы отслеживать состояние сокета и удалять объект только при приходе QAbstractSocket::UnconnectedState.

Кстати интересно, при таком подходе будет утечка памяти или нет.

Код

connect(p_new_client_connection, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(fail()));


Ведь если сигнал пихает каждый раз параметр в стек, а этот стек слот не очищает при retn считая, что у него нет параметров.

Это сообщение отредактировал(а) SABROG - 18.12.2008, 12:43


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
null56
Дата 18.12.2008, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



Сейчас создал метод getMe() {return this;}

Через него сделал в обработчике
disconnect(getMe, 0, this, 0);

После дисконекта ругнулся на QCoreApplication::postEvent: Unexpected null receiver, что в принципе логично наверное...

Цитата

Думается мне что все-таки придется делать два слота и прописать в них соотв. параметры, чтобы отслеживать состояние сокета и удалять объект только при приходе QAbstractSocket::UnconnectedState.


А в одном слоте состояние сокета нельзя проверить разьве?

Добавлено @ 12:48
Слот, я так понял неделимая операция, пока не отработает, другой сигнал его прервать не может... это видно из моего примера

Добавлено @ 12:52
Цитата

стати интересно, при таком подходе будет утечка памяти или нет.

Выделить всёкод C++
1:
    
connect(p_new_client_connection, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(fail()));


Ведь если сигнал пихает каждый раз параметр в стек, а этот стек слот не очищает при retn считая, что у него нет параметров.



Здесь в стек кладется объект QList<QSslError &> - это объект, который занимает память, утечки никак не будет

Просто доступа к этой переменной нет внутри функции, а получить через указатель стека, наверняка можно

Это сообщение отредактировал(а) null56 - 18.12.2008, 12:54
PM MAIL   Вверх
null56
Дата 18.12.2008, 13:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



Хотя хз... смотря кто стек чистит... вызывающая или вызываемая. Вот если вызываемая, то он когда не знает ничего об этой переменной, но думаю в qt все продумано, так как если бы он не удалял из стека область памяти, которую занимает эта перменная, то он бы не добрался до адреса возврата, который находится ниже в стеке, так что думаю, чистится все граммотно +
у меня в книжке от создателей написано, что если у сигнала больше параметров, чем у слота, то остальные параметры будут игнорироваться )
PM MAIL   Вверх
SABROG
Дата 18.12.2008, 13:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

Репутация: 81
Всего: 91



Да, что-то я подзабыл ассемблер smile

Это сообщение отредактировал(а) SABROG - 18.12.2008, 13:54


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
null56
Дата 18.12.2008, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: 6
Всего: 12



Конечно по хорошему надо посмотреть это дело в дебагаре, если не верить книжке, но в самом правильном случае лучше конечно разделить на два разных слота, так и гибче будет
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.0549 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.