2015-05-24 2 views
2

Я просмотрел файл boost::hold_any, и я нашел кое-что, что меня смущает. если я рассмотрю информацию, полученную из ответов на мой вопрос: What happens if you call a destructor and use the allocated memory again for other objects? (В ответе Майка Сеймура), то «запрещено» манипулировать памятью объекта, который еще не был выпущен и перераспределен, чтобы разместить там новый объект другого типа.У конструктора boost :: hold_any есть неопределенное поведение?

Я всегда думал, что библиотека форматирования придерживается стандарта, но если я не ошибаюсь, то boost::hold_any хранит небольшие объекты или переменные в памяти своего указателя содержимого (void* object), что нарушит правило, которое я нашел в ранее упомянутый ответ.

Так что я ошибаюсь или boost::hold_any нарушает стандарт? И если я ошибаюсь, где моя ошибка?

Или, если я прав, насколько надежны библиотеки ускорения, если они содержат части, которые могут вызывать неопределенное поведение?

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

EDIT Я изменил пример кода, чтобы показать, старый контент определенно уничтожен!

Это одна из точек в boost::hold_any коде, где я получил свою информацию из:

template <typename T> 
    basic_hold_any& assign(T const& x) 
    { 
     // are we copying between the same type? 
     spirit::detail::fxn_ptr_table<Char>* x_table = 
      spirit::detail::get_table<T>::template get<Char>(); 
     if (table == x_table) { 
     // if so, we can avoid deallocating and re-use memory 
      table->destruct(&object); // first destruct the old content 
      if (spirit::detail::get_table<T>::is_small::value) { 
       // create copy on-top of object pointer itself 
       new (&object) T(x); 
      } 
      else { 
       // create copy on-top of old version 
       new (object) T(x); 
      } 
     } 
     else { 
      if (spirit::detail::get_table<T>::is_small::value) { 
       // create copy on-top of object pointer itself 
       table->destruct(&object); // first destruct the old content 
       new (&object) T(x); 
      } 
      else { 
       reset();     // first delete the old content 
       object = new T(x); 
      } 
      table = x_table;  // update table pointer 
     } 
     return *this; 
    } 
+0

Подходит для обсуждения с полезными ссылками в этом чате: http://chat.stackoverflow.com/rooms/78630/discussion-between-james-adkison-and-sehe – sehe

+0

У меня был ответчик связанного вопрос исправить его ошибку/двусмысленность. Теперь есть смысл? – Yakk

+0

Да, я думаю, что теперь все ясно, спасибо :) – Mango

ответ

1

В связанном ответе, UB, что base* ptr используется в то время как он все еще указывает на этом хранилище после размещения нового был вызван, и там был создан другой объект другого типа (он используется для вызова delete). Это не относится к Boost Any. Повторное использование хранилища - это не сам UB.

+0

Как я уже показал с новым примером кода, boost делает то же самое, что и я в примере с базой * ptr (хорошо, они используют пустоту *), поэтому shouldn Это приводит к тем же проблемам? – Mango

+0

@Mango Вы называете 'delete ptr', который является UB, потому что он вызывает деструктор для' base' на объекте типа 'der1'. Указатели 'void *' не вызывают деструкторы, а Boost вызывает деструктор соответствующего типа перед удалением хранилища. – StenSoft