На какой платформе func (shared_ptr (…), shared_ptr (…)) действительно опасен?

Я помню, что Скотт Мейерс научил меня этому

func(shared_ptr(new P), shared_ptr(new Q));

опасно, потому что (если я правильно помню) порядок из выделение памяти, подсчет ссылок (строительство) и присвоение параметры функции позволяет утечка (теоретически?) появляться в редких случаях. Чтобы предотвратить это, следует заключить shared_ptr в вызове функции, например в make_shared(),

func(make_shared<P>(), make_shared<Q>());

Вот некоторые обсуждение об этом тоже.

Я хотел бы знать, есть ли (текущие) компиляторы в поле, на определенных системах это действительно может оставить какую-то дыру в некоторых случаях ошибки? Или те времена прошли, или они были только теоретическими, так или иначе?

Самое интересное было бы знать, есть ли у кого-то из них эта проблема:

  • g ++ 4.x или g ++ 2.95, на Linux i386, x64, ARM, m68k или любой Windows
  • Visual C ++ на i368, x64 или ARM
  • Clang / LLVM в Linux или любой из его платформ
  • Как насчет компиляторов C ++ на / от Sun или IBM, HP-UX?

Кто-нибудь наблюдал такое поведение на своей конкретной платформе?

4

Решение

func(shared_ptr(new P), shared_ptr(new Q));

Компилятор C ++ может реализовать это в следующем порядке:

  1. новый Q
  2. новый P
  3. построить shared_ptr вокруг выделенного P
  4. построить shared_ptr вокруг выделенного Q
  5. вызовите функционал

(Компилятор может выполнять 1, 2, 3 и 4 в любом порядке, если 1 перед 4 и 2 перед 3).

В порядке выше, если Pконструктор или вызов new броски, Q утечка памяти (память выделяется, но shared_ptr еще не построен вокруг него).

Как таковой, вы должны позвонить std::make_shared (который обрабатывает исключения при распределении изящно), и вы знаете, что когда std::make_shared вернулся за одним из них, shared_ptr полностью построен и не будет течь.

Я хотел бы знать, есть ли (текущие) компиляторы на местах, в некоторых системах, которые действительно могут оставить некоторую дыру в некоторых случаях ошибки?

Все компиляторы, соответствующие стандартам, будут иметь такое поведение.

0

Другие решения

Это не проблема платформы, это проблема безопасности исключений. Итак, ответ на ваш актуальный вопрос: все эти платформы могут демонстрировать проблему.

Проблема утечки памяти возникает из-за 2 вещей:

  • Выделение памяти с new может бросить bad_alloc
  • Порядок, в котором оцениваются аргументы функций, не указан.

Документы для boost::shared_ptr захватить это красиво Вот

Подробно об общей проблеме здесь (GOTW)

Причина, по которой это может быть «редким», возникает потому, что на самом деле это не так часто bad_alloc, но ваш код должен обрабатывать эту возможность безопасно, чтобы избежать утечек памяти.

(Я говорю «может» показать это — я не проверил, что они все бросают bad_alloc если new не может …)

4

потому что оба new Сначала будет выполнена операция, а затем они будут переданы в shared_ptrконструктор, но который shared_ptr Конструкции first не указаны, поэтому один из вновь созданных объектов может вызвать утечку памяти.

0

Это небезопасно на любой платформе с оптимизатором переупорядочения, если этот оптимизатор выполняет следующую оптимизацию A;B;A;B => A;A;B;B, Эта оптимизация повышает эффективность кэширования кода, так что в целом это хорошая идея.

Очевидно, что оптимизатор может переставлять B и A только в том случае, если их относительный порядок не указан, что здесь имеет место.

0
По вопросам рекламы [email protected]