2013-11-02 6 views
19

У меня есть кусок кода, как это:Почему первый элемент уничтожен?

class Data 
{ 
    public: 
     Data(const std::vector<int> &_data) 
     { 
      my_data = _data; 
     } 

    private: 
     std::vector<int> my_data; 
}; 


int main() 
{ 
    std::vector<std::shared_ptr<Data>> vec = { 
     std::shared_ptr<Data>(new Data(std::vector<int>({ 1, 2 ,3 }))), 
     std::shared_ptr<Data>(new Data(std::vector<int>({ 3, 4 ,5 }))) 
    }; 

    // breakpoint 

    return 0; 
} 

каким-то образом, когда я приостановить программу для проверки значений (в контрольной точке), первый элемент (vec[0]) уничтожается, а второй один (vec[1]) отлично. Что здесь происходит? Это ошибка в компиляторе? Я использую новую Visual Studio 2013.

+1

Вы отказали отладку в деструкторе 'Data :: ~ Data()' для подтверждения этого? И вы можете компилировать с помощью отладочных символов в release-сборке? – WhozCraig

+0

Да, я добавил «Data :: ~ Data()», чтобы проверить, уничтожен ли объект, и в обоих случаях Debug и Release это именно то, что произошло. – Qwrk

+0

Я вижу то же самое с приведенным выше кодом и приведенной выше настройкой. Как отладочные, так и выпускные сборки показывают одинаковое поведение. Вот результат, когда я добавляю trace 'cout' в код: * 1 * ** 'Data :: Data()' **, затем * 2 * ** 'Data :: Data()' **, затем * 3 * ** 'Data :: ~ Data()' **, затем * 4 * ** 'BREAKPOINT' ** и, наконец, * 5 * **' Data :: ~ Data() '**. – yzt

ответ

6

Случается, что ошибка в VS2013 вызывает двойное удаление в первом элементе initializer_list. Вотток:

  1. Инициализатор построен.
  2. целевой вектор зарезервирован размером 1 и первый элемент скопирован (через конструктор копирования).
  3. вектор медленно растет до размера initializer_list.
  4. Инициализатор уничтожается с помощью вектор-деструктора (то есть delete[]). Последний элемент уничтожается первым.
  5. Первый элемент снова разрушается с помощью скалярного деструктора (то есть delete).

Я видел это на другом посту и проверял поведение с помощью отладчика. См. here

Для VS2013, initializer_list подходит только для базовых типов.

0

Я думаю, что это что-то с общей записью указателя, что общий объект-указатель будет уничтожен, если уничтожается последний оставшийся shared_ptr, владеющий объектом. последнему оставшемуся shared_ptr, которому принадлежит объект, присваивается другой указатель через оператор = или reset(). Надеюсь, это поможет

0

У меня не было VS2013, поэтому я проверяю код в MinGW 4.7 в windows, я не нашел проблему выше. Когда я останавливаюсь в этой точке останова, первый элемент (vec [0]) и второй (vec [0]) элемент не уничтожаются.

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

Вы можете опубликовать код разборки выше, чтобы мы могли явно идентифицировать проблему. :)

+1

Я знаю, что это не проблема в других компиляторах, поэтому я сообщил об этом как об ошибке. Здесь [код разборки] (http://ideone.com/MRlKjU) для основной функции, я думаю, что строка 154 является причиной этой ошибки. :) И неважно, добавлю ли я лишний код после объявления или нет, похоже, что он уничтожается сразу после инициализации. – Qwrk

0

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

std::cout << __FUNCTION << ":" << this << std::endl; 

Я подтверждаю эту проблему в Visual Studio 2013. В разделе «clang» этот код ведет себя так, как ожидалось.

Смежные вопросы