Dangling pointer в std::vector.push_back() - это нормально?
От: biffant  
Дата: 09.06.08 09:55
Оценка:
VS6 SP6, BoundsChecker ругается, мол, dangling pointer в следующем случае:

inline bool MyInterface::MyFunction(
                vector <pair<long, vector<long> > >      &  MyVector
            )
{
<...>
if(SomeCondition)
      {
      pair<long, vector<long> > MyPair;
      long MyVar1, MyVar2;

      <...>

      MyPair.first = MyVar1;
      MyPair.second.push_back(vector<long>::value_type(MyVar2));

      MyVector.push_back(vector<pair<long, vector<long> > >::value_type(MyPair));
      }
<...>
}


Во время исполнения второго push_back, в <vector> возникает "висячий указатель".

Далее везде, для удобства чтения, используем
typedef struct std::pair<long,class std::vector<long,class std::allocator<long> > > MyStruct;


Current Call stack:

vector<MyStruct,class std::allocator<MyStruct> >::size
vector<MyStruct,class std::allocator<MyStruct> >::insert
vector<MyStruct,class std::allocator<MyStruct> >::insert
vector<MyStruct,class std::allocator<MyStruct> >::push_back
MyFunction


Allocation Call stack:

_Allocate    <xmemory>
allocator<MyStruct>::allocate    <xmemory>
vector<MyStruct,class std::allocator<MyStruct> >::insert    <vector>
vector<MyStruct,class std::allocator<MyStruct> >::insert    <vector>
vector<MyStruct,class std::allocator<MyStruct> >::push_back    <vector>


Deallocation Call stack:
allocator<MyStruct>::deallocate    <xmemory>
vector<MyStruct,class std::allocator<MyStruct> >::insert    <vector>
vector<MyStruct,class std::allocator<MyStruct> >::insert    <vector>
vector<MyStruct,class std::allocator<MyStruct> >::push_back    <vector>
MyFunction


Что происходит в <vector>:
void push_back(const _Ty& _X)
        {insert(end(), _X); }

Далее
iterator insert(iterator _P, const _Ty& _X = _Ty())
        {size_type _O = _P - begin();
        insert(_P, 1, _X);
        return (begin() + _O); }

Далее в insert()
void insert(iterator _P, size_type _M, const _Ty& _X)
        {if (_End - _Last < _M)
            {size_type _N = size() + (_M < size() ? size() : _M);
            iterator _S = allocator.allocate(_N, (void *)0);
            iterator _Q = _Ucopy(_First, _P, _S);
            _Ufill(_Q, _M, _X);
            _Ucopy(_P, _Last, _Q + _M);
            _Destroy(_First, _Last);
            allocator.deallocate(_First, _End - _First);
            _End = _S + _N;
            _Last = _S + size() + _M;
            _First = _S; }
                 <...>
                 }

Здесь он заходит в size() предпоследней строчки:
size_type size() const
        {return (_First == 0 ? 0 : _Last - _First); }

В результате, видим "Dangling Pointer: Pointer 0x054BE528, allocated by global_operator_new, has already been freed."

ВОПРОС — это просто особенность STL, либо я могу как-то исправить ситуацию при вызове std::vector.push_back()?

Буду признателен за любую помощь!
STL Vector BoundsChecker
Re: Dangling pointer в std::vector.push_back() - это нормаль
От: Bell Россия  
Дата: 09.06.08 11:58
Оценка: 2 (1)
Здравствуйте, biffant, Вы писали:

B>ВОПРОС — это просто особенность STL, либо я могу как-то исправить ситуацию при вызове std::vector.push_back()?


Похоже, что это особенность BoundsChecker-а. Никакого криминала в приведенном коде быть не должно

Раз речь о VC6, в любом случае исеет смысл посмотреть в сторону STLPort. Даже если это не решит проблемы с BoundsChecker, потому как "родная" реализация STL имеет кучу недостатков.

Быть может имеет смысл рассмотреть вариант, кода в векторе хранятся (умные) указатели на MyStruct...
Любите книгу — источник знаний (с) М.Горький
Re[2]: Dangling pointer в std::vector.push_back() - это норм
От: biffant  
Дата: 09.06.08 12:24
Оценка:
Здравствуйте, Bell, Вы писали:

B>Похоже, что это особенность BoundsChecker-а. Никакого криминала в приведенном коде быть не должно

Если workaround не существует, странно что ни в known issues, ни в гугле, ни здесь ничего похожего не нашел. Аналогичных ошибок в данном проекте BoundsChecker генерит много, приблизительно 10% всех вызовов std::vector.push_back()

B>Раз речь о VC6, в любом случае исеет смысл посмотреть в сторону STLPort. Даже если это не решит проблемы с BoundsChecker, потому как "родная" реализация STL имеет кучу недостатков.

Речь о VC6 и его "дефолтном" STL потому что это большой, многолетний production-проект, над которым работаю далеко не только я. Соответственно переход на STLPort, равно как и на более современную студию, вопрос весьма непростой

B>Быть может имеет смысл рассмотреть вариант, кода в векторе хранятся (умные) указатели на MyStruct...

Тоже над этим думал, однако подобный рефакторинг выглядит слишком серьёзным для такой "косметической" проблемы, учитывая количество таких "проблемных" вызовов, переход везде на smart pointers выглядит нецелесообразно

Вероятно, просто сделаю supress на данную ошибку. Спасибо за отклик!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.