shared_ptr
May. 2nd, 2014 10:28 pmПопытался использовать shared_ptr из C++11. Ну что я могу сказать, люди, создавшие напрочь бесполезный auto_ptr, сумели создать почти столь же бесполезный счетчик ссылок. Фундаментальная проблема в том, что они пытаются делать счетчик ссылок для совершенно любых структур, и потому хранят сам счетчик не прямо в структуре, а отдельно. При присвоении указателя в shared_ptr в первый раз оно создает отдельную структуру со счетчиком. И если потом присваивать эти shared_ptr друг к другу, то оно работает нормально. Но если взять и опять положить изначальный указатель в другой shared_ptr, то образуется два отдельных счетчика для одной структуры, и все погибает. И совершить такую ошибку очень легко. В-общем, этой штукой пользоваться нельзя. Мой темплейт Autoptr - гораздо, гораздо лучше.
P.S. Проблема разъяснилась. Надо просто никогда не конструировать такие объекты напрямую, а использовать make_shared. Ну, или статические методы, возвращающие прямо ссылку. И тогда указатели не вылазят наружу.
P.S. Проблема разъяснилась. Надо просто никогда не конструировать такие объекты напрямую, а использовать make_shared. Ну, или статические методы, возвращающие прямо ссылку. И тогда указатели не вылазят наружу.
no subject
Date: 2014-05-03 05:35 am (UTC)А это разве не поперек идеологии RAII? Получил поинтер / хендл, засунь в смартпоинтер и убери руки. Брать и положить нельзя.
no subject
Date: 2014-05-03 05:44 am (UTC)no subject
Date: 2014-05-03 05:56 am (UTC)А где посмотреть как именно вы считаете рефкаунты?
no subject
Date: 2014-05-03 06:27 am (UTC)Вкратце описано оно здесь:
http://babkin-cep.blogspot.com/2012/08/reference-counting.html
http://babkin-cep.blogspot.com/2012/08/autoref-summary.html
И код тут:
http://sourceforge.net/p/triceps/code/HEAD/tree/trunk/cpp/mem/
no subject
Date: 2014-05-03 06:33 am (UTC)no subject
Date: 2014-05-03 06:42 am (UTC)no subject
Date: 2014-05-03 06:10 am (UTC)no subject
Date: 2014-05-03 06:17 am (UTC)no subject
Date: 2014-05-03 06:24 am (UTC)no subject
Date: 2014-05-03 06:30 am (UTC)no subject
Date: 2014-05-03 06:34 am (UTC)Я еще не читал, но это пахнет комом. Не то чтобы с комом что-то было не так, но все украдено до нас, и есть проблема с кольцевыми ссылками.
no subject
Date: 2014-05-03 06:46 am (UTC)no subject
Date: 2014-05-03 07:17 am (UTC)no subject
Date: 2014-05-03 07:26 am (UTC)no subject
Date: 2014-05-03 11:04 am (UTC)no subject
Date: 2014-05-03 04:32 pm (UTC)no subject
Date: 2014-05-03 07:35 am (UTC)shared_ptr<Object> p = new Object;
somewhere->field_shared_ptr = p;
Ну, или в одну строчку
somewhere->field_shared_ptr = shared_ptr<Object>(new Object);
somewhere->field_shared_ptr = make_shared<Object>(new Object);
no subject
Date: 2014-05-03 07:40 am (UTC)no subject
Date: 2014-05-03 04:05 pm (UTC)но я про бустовую версию
no subject
Date: 2014-05-03 04:37 pm (UTC)Вообще, конечно, с точки зрения эффективности оно все равно проигрывает, с лишними копированиями ссылок и изменениями счетчика, но это уже фигня, жить можно.
no subject
Date: 2014-05-03 08:10 pm (UTC)а передавать можно и реф на шейрд, там где копировать не нужно
я бустовые шейрды использую уже лет 10 наверное, даже если есть оверхед в 1-2%, это покрывается кастомными аллокаторами ну и просто тем что руками с памятью работать не нужно
кстати в майкрософте народ как-то умудрился оптимизировать shared_ptr, надо почитать, gcc'шная версия по крайней мере на 4.7 проигрывала
еще есть нюанс при сильно многопоточной обработке, если вдруг в дизайне (по ошибке) есть набор каких-то шейрдов, которые зачем-то часто копируются/удаляются и они рядом в памяти, то могут быть проблемы с когерентностью кэш-линий (в том плане что копирование адски замедляется), надо их как-нибудь раскидать в памяти или передизайнить
no subject
Date: 2014-05-03 11:12 pm (UTC)no subject
Date: 2014-05-03 07:23 am (UTC)Но вообще похоже, что я догадался, как надо делать с shared_ptr чтобы он не ломался: во всех классах, предназначенных для использования с ним, делать конструкторы защищенными, а вместо них использовать статические функции, которые будут возвращать сразу shared_ptr (возможно, делая make_shared, но непонятно, не делает ли он копирования объекта). И тогда простые указатели совсем исчезают, и сломать логику делается сложно.
no subject
Date: 2014-05-03 04:02 pm (UTC)ой, ну да, дочитал :)
кстати. проблемы с оборачиванием одной и той же структуры в два шейрда ни разу не наблюдал
no subject
Date: 2014-05-03 04:35 pm (UTC)no subject
Date: 2014-05-03 08:13 pm (UTC)полезно при всякой там асинхронной обработке через boost::asio например