Russian Qt Forum

Qt => Вопросы новичков => Тема начата: mos4ever от Июнь 19, 2012, 20:18



Название: проверка объекта на существование по указателю
Отправлено: mos4ever от Июнь 19, 2012, 20:18
Помогите! Есть код:
QObject *ptr = new QObject();
delete ptr;

как проверить после удаления объекта по указателю его существование?


Название: Re: проверка объекта на существование по указателю
Отправлено: alexis031182 от Июнь 19, 2012, 20:23
QPointer


Название: Re: проверка объекта на существование по указателю
Отправлено: Fat-Zer от Июнь 19, 2012, 20:41
вообще говоря, никак. надо писать delete ptr; ptr=0;


Название: Re: проверка объекта на существование по указателю
Отправлено: shirushizo от Июнь 20, 2012, 13:08
Обратиться к свойствам ptr, если приложение высыпется, то объект уже разрушен. :)

Лучше опиши, чего ты хочешь добиться и для чего будешь это использовать.


Название: Re: проверка объекта на существование по указателю
Отправлено: mutineer от Июнь 20, 2012, 13:10
Обратиться к свойствам ptr, если приложение высыпется, то объект уже разрушен. :)

Ну вот не факт что такое обращение приведет к падению. На месте старого объекта вполне уже может быть расположен новый


Название: Re: проверка объекта на существование по указателю
Отправлено: alexis031182 от Июнь 20, 2012, 13:10
Обратиться к свойствам ptr, если приложение высыпется, то объект уже разрушен. :)
...
Ой, не зря русскую рулетку называют русской ;D


Название: Re: проверка объекта на существование по указателю
Отправлено: Kurles от Июнь 20, 2012, 13:12
Помогите! Есть код:
QObject *ptr = new QObject();
delete ptr;

как проверить после удаления объекта по указателю его существование?
Код
C++ (Qt)
if (qobject_cast<QObject*>(ptr))
   {
       //что то там есть
   }
Только смысл?


Название: Re: проверка объекта на существование по указателю
Отправлено: Serr500 от Июнь 20, 2012, 13:33
Код
C++ (Qt)
if (qobject_cast<QObject*>(ptr))
   {
       //что то там есть
   }
А с чего Вы взяли, что после delete qobject_cast обязано будет вернуть NULL?


Название: Re: проверка объекта на существование по указателю
Отправлено: shirushizo от Июнь 20, 2012, 16:16
Ну вот не факт что такое обращение приведет к падению. На месте старого объекта вполне уже может быть расположен новый
Если уже есть новый, то объект существует, все верно=)

По-хорошему:
вообще говоря, никак. надо писать delete ptr; ptr=0;
и проверять ptr==0. Но при асинхронных процессах, есть шанс проверить ptr==0 между delete ptr; и ptr=0; (это уже другой вопрос)
Или использовать "умные" указатели, но, на сколько мне известно, 100% гарантии они все же не дают.


Название: Re: проверка объекта на существование по указателю
Отправлено: mutineer от Июнь 20, 2012, 16:21
Ну вот не факт что такое обращение приведет к падению. На месте старого объекта вполне уже может быть расположен новый
Если уже есть новый, то объект существует, все верно=)

что верно-то? в этом куске памяти может быть абсолютно любой объект, любого типа. и начинаться он может не с этого адреса, а раньше


Название: Re: проверка объекта на существование по указателю
Отправлено: Serr500 от Июнь 20, 2012, 16:51
и проверять ptr==0. Но при асинхронных процессах, есть шанс проверить ptr==0 между delete ptr; и ptr=0; (это уже другой вопрос)
Или использовать "умные" указатели, но, на сколько мне известно, 100% гарантии они все же не дают.

Код:
void My_Delete(T** p)
{
    mutex->lock();
    delete *p;
    *p = NULL;
    mutex->unlock();
}


Название: Re: проверка объекта на существование по указателю
Отправлено: Igors от Июнь 20, 2012, 17:43
Код:
void My_Delete(T** p)
{
    mutex->lock();
    delete *p;
    *p = NULL;
    mutex->unlock();
}
Так затрачивается дорогостоящая блокировка и вынуждается ** везде. А достигается только что 2 нитки не удалят. Маловато, напр если др нитка использует *p - она рухнет после его удаления. QSharedPointer смотрится выгоднее


Название: Re: проверка объекта на существование по указателю
Отправлено: fuCtor от Июнь 23, 2012, 21:36
и проверять ptr==0. Но при асинхронных процессах, есть шанс проверить ptr==0 между delete ptr; и ptr=0; (это уже другой вопрос)
Или использовать "умные" указатели, но, на сколько мне известно, 100% гарантии они все же не дают.

Код:
void My_Delete(T** p)
{
    mutex->lock();
    delete *p;
    *p = NULL;
    mutex->unlock();
}

Уже все придумано: http://doc.qt.nokia.com/4.7-snapshot/qatomicpointer.html


Название: Re: проверка объекта на существование по указателю
Отправлено: Serr500 от Июнь 23, 2012, 21:43
Код:
QAtomicPointer<T> p;
T* pT = p.fetchAndStoreRelaxed(NULL);
delete pT;
Я правильно понял?


Название: Re: проверка объекта на существование по указателю
Отправлено: Igors от Июнь 24, 2012, 12:40
Код:
QAtomicPointer<T> p;
T* pT = p.fetchAndStoreRelaxed(NULL);
delete pT;
Я правильно понял?
Так p надо инициализировать и потом уже отдать всем ниткам, т.е. они должны извлекать реальный указатель из p. Тогда двойное удаление исключается, но толку от этого немного - ведь обращения по указателю ставшему нулевым остаются

Уже все придумано: http://doc.qt.nokia.com/4.7-snapshot/qatomicpointer.html
А зачем нужен это класс если чтение/запись указателей и так атомарны?
Обычно чем больше классов человек знает - тем хуже он отвечает на такие вопросы. Ну посмотрим, может в этот раз будет "приятное исключение"  :)


Название: Re: проверка объекта на существование по указателю
Отправлено: fuCtor от Июнь 24, 2012, 13:16
Уже все придумано: http://doc.qt.nokia.com/4.7-snapshot/qatomicpointer.html
А зачем нужен это класс если чтение/запись указателей и так атомарны?
Обычно чем больше классов человек знает - тем хуже он отвечает на такие вопросы. Ну посмотрим, может в этот раз будет "приятное исключение"  :)

Чтение/запись да, но ИМХО основная цель атомарных классов (как их правильней назвать хз) сделать атомарной операцию сравнение с присваиванием, чтение с присваиванием и т.п. В обычном случае, это несколько отдельных команд, в процессе выполнения которых может быть гонка.

Код:
QAtomicPointer<T> p;
T* pT = p.fetchAndStoreRelaxed(NULL);
delete pT;
Я правильно понял?

Я бы еще добавил проверку инициализации указателя в виде:
Код:
QAtomicPointer<T> p; //общий указатель на что-то, который инициализирует один из потоков, а остальные используют
// следовательно нужна проверить был ли указатель уже создан
if(!p)
{
  T * pt = new T;
  if( !p.testAndSetRelaxed(0, pt) )
  {
    delete pt;
  }
}

Таким образом если указатель пуст, то ему будет присвоено значение, тогда другие проходя эту точку уже увидят, что значение не нулевое и удалят временный объект. Как-то так. А удаление да, как указано у вас можно реализовать, тоже будет исключена гонка между чтением - записью.

UPD: поправил сообщение в контексте вопроса  ::)


Название: Re: проверка объекта на существование по указателю
Отправлено: Igors от Июнь 24, 2012, 16:54
Таким образом если указатель пуст, то ему будет присвоено значение, тогда другие проходя эту точку уже увидят, что значение не нулевое и удалят временный объект. Как-то так.
Так-то оно так, но действие странное: создали новый указатель, пытаемся его подсунуть, не получилось - удаляем созданный. Затрудняюсь придумать когда это нужно. Во всяком случае гораздо чаще нужно заменить предыдущий указатель на новый, а старый удалить.
Код
C++ (Qt)
void ReplacePtr( T *& oldP, T * newP )
{
// ???
}
 
Serr500 уже предложил 2 рабочих варианта, однако в первом дорогой мутекс, а во втором нам придется везде тащить/объявлять QAtomicPointer, что конечно пережить можно, но хотелось бы иметь нормальный указатель, а в нужный момент (и используя нужные классы внутри ReplacePtr) его заместить. Как это сделать?


Название: Re: проверка объекта на существование по указателю
Отправлено: fuCtor от Июнь 24, 2012, 17:16
Таким образом если указатель пуст, то ему будет присвоено значение, тогда другие проходя эту точку уже увидят, что значение не нулевое и удалят временный объект. Как-то так.
Так-то оно так, но действие странное: создали новый указатель, пытаемся его подсунуть, не получилось - удаляем созданный. Затрудняюсь придумать когда это нужно. Во всяком случае гораздо чаще нужно заменить предыдущий указатель на новый, а старый удалить.
Код
C++ (Qt)
void ReplacePtr( T *& oldP, T * newP )
{
// ???
}
 
Serr500 уже предложил 2 рабочих варианта, однако в первом дорогой мутекс, а во втором нам придется везде тащить/объявлять QAtomicPointer, что конечно пережить можно, но хотелось бы иметь нормальный указатель, а в нужный момент (и используя нужные классы внутри ReplacePtr) его заместить. Как это сделать?


Как вариант использовать активное ожидание и локальный статичный QAtomicInt как Spinlock:
Код
C++ (Qt)
void ReplacePtr( T *& oldP, T * newP )
{
  static QAtomicInt spinlock = 0;
  while(!spinlock.testAndSetRelaxed(0, 1));
  // тут делаем нужные операции, например
  if(oldP)
    delete oldP;
  oldP = newP;
  spinlock = 0; //Обязательно после всего и обязательно должен выполниться, иначе deadlock
}
 
Т.к. предполагается что тело функции маленькое, то можно сделать и так, ну подождет пару тактов в цикле, все быстрей чем мьютексы ворочить.


Название: Re: проверка объекта на существование по указателю
Отправлено: Igors от Июнь 24, 2012, 17:34
Т.к. предполагается что тело функции маленькое, то можно сделать и так, ну подождет пару тактов в цикле, все быстрей чем мьютексы ворочить.
Так намного круче (атомарный лок куда быстрее). И лучше писать testAndSetAcquire - яснее чего хотим. Все же нельзя ли чище, без доп атомарной переменной?


Название: Re: проверка объекта на существование по указателю
Отправлено: fuCtor от Июнь 24, 2012, 17:54
Т.к. предполагается что тело функции маленькое, то можно сделать и так, ну подождет пару тактов в цикле, все быстрей чем мьютексы ворочить.
Так намного круче (атомарный лок куда быстрее). И лучше писать testAndSetAcquire - яснее чего хотим. Все же нельзя ли чище, без доп атомарной переменной?

Код
ASM
mov eax, spinlock_address
mov ebx, SPINLOCK_BUSY
wait_cycle:
lock xchg [eax], ebx
cmp ebx, SPINLOCK_FREE
jnz wait_cycle
 
;<body>
 
mov eax, spinlock_address
mov ebx, SPINLOCK_FREE
lock xchg [eax], ebx
 
Взято с http://ru.wikipedia.org/wiki/Spinlock  ;D

А так без атомарных ИМХО никак, другие (их тех что знаю) не дают 100% гарантии в отсутствии гонки.


Название: Re: проверка объекта на существование по указателю
Отправлено: shirushizo от Июнь 25, 2012, 10:52
Горячие финские парни, про потоки я упомянул вскользь и уже об этом жалею :)
Слишком далеко ушли от вопроса темы ;)


Название: Re: проверка объекта на существование по указателю
Отправлено: Igors от Июнь 25, 2012, 11:27
Горячие финские парни, про потоки я упомянул вскользь и уже об этом жалею :)
Слишком далеко ушли от вопроса темы ;)
Жалеть надо автора темы, который играется с чужими классами не понимая языка  :)
В С/C++ нет средств проверки валидности адреса, известно лишь что 0-адрес невалиден. Никогда не понимал почему такие вопросы привлекают и получают немало ответов

Взято с http://ru.wikipedia.org/wiki/Spinlock  ;D

А так без атомарных ИМХО никак, другие (их тех что знаю) не дают 100% гарантии в отсутствии гонки.
Все-таки лучше так
Код
C++ (Qt)
void ReplacePtr( T *& oldP, T * newP )
{
  static QAtomicInt spinlock = 0;
  while(!spinlock.testAndSetAcquire(0, 1)) {}
  T * doomed = oldP;
  oldP = newP;
  spinlock = 0;
  delete doomed;
}
Т.к. вызов delete (с эвентуальным деструктором) - совсем не пара тактов
А можно и без статика
Код
C++ (Qt)
template <class T>
void ReplacePtr( T *& oldP, T * newP )
{
T * doomed;
typedef QAtomicPointer <T> TAtom;
TAtom * ta = (TAtom *) &oldP;
for (;;) {
doomed = oldP;
if (ta->testAndSetAcquire(doomed, newP)) break;
}
delete doomed;
}
 
Несмотря на обилие Qt классов - не вижу как записать без приведения.