Russian Qt Forum
Май 17, 2024, 21:24 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3] 4   Вниз
  Печать  
Автор Тема: qDeleteAll - глупый и опасный метод!  (Прочитано 40085 раз)
mutineer
Гость
« Ответ #30 : Июнь 05, 2012, 12:53 »

frostyland, а как ты будешь QMap и QHash обрабатывать, если ключи тоже указатели и еще будут использоваться?
Ключ-указатель смысла не имеет т.к операторы  == и < не дадут разумного результата. А с мыслью согласен - ситуаций когда что-то остается невалидным после вызова метода или ф-ции сколько угодно

QSignalMapper использует ключ-указель для QHash, и это имеет смысл
Записан
frostyland
Гость
« Ответ #31 : Июнь 05, 2012, 12:54 »

Никто тут за исключением одного умника никого дураком не мнит, друзья!
Я просто утверждаю, что за пределами видимости использования метода qDeleteAll вы получите скорлупку с гнилым содержимым, а не контейнер.

Еще раз, речь вот об этом.

Код
C++ (Qt)
class Test
{
public:
   Test(const char* text) : m_size(20), m_buf(0)
   {
       init(text);
   }
 
   ~Test()
   {
       if(m_buf != 0){
           free(m_buf);
       }
   }
 
   void init(const char* text)
   {
       if(m_buf == 0){
           m_buf = (char*)realloc(m_buf, m_size);
       }
       strncpy(m_buf, text, m_size-1);
   }
 
   const char* get() const
   {
       return m_buf;
   }
private:
   const int m_size;
   char* m_buf;
};
 
typedef QVector<Test*> TestVector_t;
 
void doItNice(TestVector_t& vector)
{
   qDeleteAll(vector);
   vector.clear();
}
 
void doItAsIdiot(TestVector_t& vector)
{
   qDeleteAll(vector);
}
 
 
int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
 
   const int _size = 10;
 
   {
       TestVector_t _vector;
       for(int _i = 0; _i < _size; ++_i){
           Test* _test = new Test("Nice and good!");
           _vector.push_back(_test);
       }
       int _count = _vector.size();
       doItNice(_vector);
       _count = _vector.size();
// Variant 1. OK! _count is valid!
       if(_count){
           for(int _i = 0; _i < _size; ++_i){
               Test* _obj = _vector[_i];
               const char* _str = _obj->get();
               printf(_str);
           }
       }
   }
 
   {
       TestVector_t _vector;
       for(int _i = 0; _i < _size; ++_i){
           Test* _test = new Test("Nice and good!");
           _vector.push_back(_test);
       }
       int _count = _vector.size();
       doItAsIdiot(_vector);
// Variant 2. FUCK! _count is fail!
       _count = _vector.size();
       if(_count){
           for(int _i = 0; _i < _size; ++_i){
               Test* _obj = _vector[_i];
               const char* _str = _obj->get();
               printf(_str);
           }
       }
   }
 
   return a.exec();
}
 

Variant 1
вот он - сторож контейнера - его размер.
Никак иначе не убедиться, что в контейнере ковыряться ОПАСНО!

Variant 2.
А здесь вы ПОПАЛИ!
Размер вас жестко обманет, и пипец памяти на машине клиента.
Он Вам однозначно скажет спасибо.
Как будете проверять? А??? А???

-----------------
Это опасное поведение. Вы никогда не можете предполагать, кто и как оперировал элеметами невалидного контейнера.
Писать такое, защищать такое - простительно 25-летним кодерам, которые еще институтские пирожки не повыкакали. Ну или тем, кто манипулирует только своим кодом, а никак не чужим. А если Вы, как иногда и я, работаете с чужим кодом, к исходника\м которого не имеете доступа, и вдруг получаете из какого нибудь метода ссылку на контейнер, Вам остается только молиться, что там не использовалось qDeleteAll без связки с clear...
Записан
frostyland
Гость
« Ответ #32 : Июнь 05, 2012, 13:08 »

Мне лень смотреть, но наверняка qDeleteAll используется в деструкторе QObject, поскольку там имеено такое отношение Parent - Children.
Что-то не нашел я там использования qDeleteAll. кутишнки сами используют крайне редко, только в деструкторах, ну и в примерах, всегда добавляя .clear()
даже себе они не позволяют лишний раз использовать эту бомбу замедленного действия...
« Последнее редактирование: Июнь 05, 2012, 13:14 от frostyland » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #33 : Июнь 05, 2012, 13:28 »

Еще раз, речь вот об этом.
Ну знаете, приведенный Вами текст содержит такие "пирожки" что по сравнению с ними qDeleteAll - да просто "персик" Улыбающийся  Хотите - покритикуем
Записан
frostyland
Гость
« Ответ #34 : Июнь 05, 2012, 13:34 »

Я намеренно сделал его простым. Зато это работающий код, а не псевдо-лапша...
Концентрируйтесь на сути.
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #35 : Июнь 05, 2012, 13:35 »

Цитировать
Это опасное поведение. Вы никогда не можете предполагать, кто и как оперировал элеметами невалидного контейнера.
Писать такое, защищать такое - простительно 25-летним кодерам, которые еще институтские пирожки не повыкакали. Ну или тем, кто манипулирует только своим кодом, а никак не чужим. А если Вы, как иногда и я, работаете с чужим кодом, к исходника\м которого не имеете доступа, и вдруг получаете из какого нибудь метода ссылку на контейнер, Вам остается только молиться, что там не использовалось qDeleteAll без связки с clear...

http://www.youtube.com/watch?v=urMtPiRUknY  
Не удержался)

А Вам сколько лет, если не секрет?
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4730



Просмотр профиля WWW
« Ответ #36 : Июнь 05, 2012, 13:35 »

Мне лень смотреть, но наверняка qDeleteAll используется в деструкторе QObject, поскольку там имеено такое отношение Parent - Children.
Что-то не нашел я там использования qDeleteAll. кутишнки сами используют крайне редко, только в деструкторах, ну и в примерах, всегда добавляя .clear()
даже себе они не позволяют лишний раз использовать эту бомбу замедленного действия...
поиск по исходникам дал 243 matches across 92 files - не так уж и редко. и clear() там вызывается далеко не везде.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #37 : Июнь 05, 2012, 13:41 »

Я намеренно сделал его простым. Зато это работающий код, а не псевдо-лапша...
Концентрируйтесь на сути.
Ой вряд ли он работающий. Значит, я так понял, критиковать не надо?  Улыбающийся
Записан
frostyland
Гость
« Ответ #38 : Июнь 05, 2012, 13:46 »

поиск по исходникам дал 243 matches across 92 files - не так уж и редко. и clear() там вызывается далеко не везде.
1/2 - examples & demos, остальные - в деструкторах, или в связке. Просмотрел почти все вхождения.
Записан
frostyland
Гость
« Ответ #39 : Июнь 05, 2012, 13:50 »

Ой вряд ли он работающий. Значит, я так понял, критиковать не надо?  Улыбающийся
Елы-палы. Компилируйте, проверяйте, уважаемый (приаттачка).
Критикуйте СУТЬ топика - неотлавливаемые никак хвосты неинициализированной памяти после применения qDeleteAll.

Задача была показать на работающем коде опасность работы с контейнерами после операции над ними опасного и глупого метода qDeleteAll. Ключевое слово - работающий код. В противовес показана безопасность работы связки qDeleteAll+clear().

В нормальном программировании, где безопасность кода - одна из главных задач, за написание, использование, отстаивание правильности для внешнего использования такого метода, кодер бы лишился премии минимум, а скорее всего и работы.
Выдача наружу хвостов неинициализированной памяти - это мега-зло. Сомнительная экономия ресурсов ради очевидной опасности покрушить память - мега-зло.
« Последнее редактирование: Июнь 05, 2012, 14:02 от frostyland » Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3259


Просмотр профиля
« Ответ #40 : Июнь 05, 2012, 13:58 »

Не понимаю наездов хомячков на qDeleteAll. Он _намеренно_ сделан не очищающим контейнер, чтобы повысить производительность. Нахрена делать deleteAll и потом этот контейнер использовать? Я что-то задач мало вижу реальных. Он либо используется в деструкторе, либо не используется вовсе - в случае поштучной/груповой работы с контейнером.
А в тех случаях, когда нужно переиспользовать контейнер, можно и clear() написать - не обломитесь. С него, кстати, лучше начинать. Если вы напишите qDeleteAll() и забудете clear(), вы быстро об этом узнаете, поверьте.
Записан
frostyland
Гость
« Ответ #41 : Июнь 05, 2012, 14:09 »

прематуре оптимизайшен это что? это рут ов зе олл ивел, знаете ли )))))))

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

"Ваша программа постоянно падает"
"Зато она такая быстрая, что падает чаще других в один и тот же отрезок времени!!"
Записан
DmitryM
Гость
« Ответ #42 : Июнь 05, 2012, 14:18 »

Вы, уважаемый хам, сейчас написали ерунду. qDeleteAll - это метод (function), что следует как из понятия "функция", так и из документации Qt на qDeleteAll (почитайте, это несложно, правда, по-английски).
И зачем Вы здесь приплели обобщенное программирование, мне тоже не понятно. Это никак не относится к вопросу. Умничаете?
Читаем доку по QtAlgorithms там где-нибудь встречается слово метод? Нет там этого слова, и qDeleteAll не является членом-функцией какого либо класса. Однако там везде написано, что это алгоритмы. Читаем дальше там везде идут ссылки на STL.
А STL это у нас:
Цитировать
набор согласованных обобщённых алгоритмов, контейнеров ...

Записан
Akon
Гость
« Ответ #43 : Июнь 05, 2012, 14:22 »

2frostyland:
В тех примерах, что вы привели, использование qDeleteAll без clear - глупость. Никто вменяемый так не поступит. Но это не единственный способ использования qDeleteAll! Есть и другие способы, для которых qDeleteAll подходит.
Записан
DmitryM
Гость
« Ответ #44 : Июнь 05, 2012, 14:25 »

.clear() просто должно было быть там по умолчанию в реализации qDeleteAll.
Не должен, т. к. требует от контейнера наличие этого самого clear()
Если у меня есть контейнер реализующий дерево или граф, то метод clear я захочу назвать как-нибудь по другому, что бы кто попало его не вызывал.
Записан
Страниц: 1 2 [3] 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.091 секунд. Запросов: 22.