В общем такие проблемы обычно решаются довольно быстро.
Но тут вообще в ступор встал.
В общем вылетает с эксепшином у меня вот в таком месте:
virtual bool some_member_func(std::string& a)
{
m_some_member_string += a; //m_some_member_string - тоже std::stringreturn true;
}
Исключение происходит на выделении памяти, потому что новый размер неадекватно большой (0x2dcf9d70).
Но, что самое интересное: состояние обоих переменных нормальное.
Переменная m_some_member_string (она фактически пустая):
+ std::_String_val<char,std::allocator<char> > {_Alval={...} } std::_String_val<char,std::allocator<char> >
npos 0xffffffff const unsigned int
+ _Bx {_Buf=0x04aeef58 "" _Ptr=0x2e900000 <Bad Ptr> } std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Bxty
_Mysize 0x00000000 unsigned int
_Myres 0x0000000f unsigned int
Переменная а(в ней 16 байт записано):
+ std::_String_val<char,std::allocator<char> > {_Alval={...} } std::_String_val<char,std::allocator<char> >
npos 0xffffffff const unsigned int
+ _Bx {_Buf=0x04aedf08 "8’™ММММММММММММ" _Ptr=0x03999238 "502 Unknown Host" } std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Bxty
_Mysize 0x00000010 unsigned int
_Myres 0x0000009f unsigned int
Что-то нелепое происходит в файле xstring line 954:
_Myt& __CLR_OR_THIS_CALL append(const _Myt& _Right,
size_type _Roff, size_type _Count)
{ // append _Right [_Roff, _Roff + _Count)if (_Right.size() < _Roff)
_String_base::_Xran(); // _Roff off endsize_type _Num = _Right.size() - _Roff;//каким-то нелепым образом, в значение _Num попадает 0x2dcf9d70, хотя я ясно вижу в отладчике что _Right.size() равен 16 а _Roff = 0!!!if (_Num < _Count)
_Count = _Num; // trim _Count to sizeif (npos - _Mysize <= _Count || _Mysize + _Count < _Mysize)
_String_base::_Xlen(); // result too longif (0 < _Count && _Grow(_Num = _Mysize + _Count))
{ // make room and append new stuff
_Traits_helper::copy_s<_Traits>(_Myptr() + _Mysize, _Myres - _Mysize,
_Right._Myptr() + _Roff, _Count);
_Eos(_Num);
}
return (*this);
}
Обе этих переменных 100% используются только в этом потоке, никто к ним доступа не имеет.
Я сначала думал что какой-то другой поток затер в памяти эту переменную после вычисления реальной длины, но ошибка воспроизводится ровно в том же месте каждый раз.
У кого есть какие мнения как ловить багу.
Я склоняюсь все таки в сторону что кто-то херит память... но как ловить ?
Здравствуйте, Аноним, Вы писали:
А>У кого есть какие мнения как ловить багу. А>Я склоняюсь все таки в сторону что кто-то херит память... но как ловить ?
Последний раз я встречал точно такую же ошибку (и тоже проявлялось на std::string) в
одной библиотеке для разбора JSON. Там в целях экономии оперативки предлагалось
пожертвовать выравниванием данных — в результате кое-где проскакивали экземпляры
строки, выравненные абы как. Точнее говоря, никак не выравненные.
В результате программа падала на строке типа std::string Str1 = Str2 + Str3.
А>У кого есть какие мнения как ловить багу. А>Я склоняюсь все таки в сторону что кто-то херит память... но как ловить ?
Поставить break on write access (ba w в widbg) на это поле строки когда оно валидно и ждать пока его кто-нить расхерачит. Если строка конечно не меняется часто.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, rus blood, Вы писали:
RB>Здравствуйте, Аноним, Вы писали:
RB>Показывай, как вызывается функция, и как создается для нее аргумент.
Не могу. Функция вызывается из другой функции та из другой и т.д.
Могу сказать только что этот код работает долго (несколько часов) и вызывается тысячи раз, после чего происходит эта шляпка.
Переменная которая передается по ссылке создается на стеке на 6 шесть вызовов вверх по стеку, и она точно целая и невредимая. В отладчике это хорошо видно.
Переменная в которую делается присваивание (переменная член) — создается вместе с экземпляром класса.
Здравствуйте, Андрей, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>skip
А>а если сигнатуру поменять? А>на some_member_func(std::string a) или хотя бы на some_member_func(const std::string& a)?
А смысл? Вы хотите сказать что строки которые передаются по ссылке нельзя конкатенировать ?
Я не совсем уловил ход Ваших мыслей...
Здравствуйте, Ytz, Вы писали:
Ytz>Здравствуйте, Аноним, Вы писали:
А>>
А>>virtual bool some_member_func(std::string& a)
А>>{
А>> m_some_member_string += a; //m_some_member_string - тоже std::string
А>> return true;
А>>}
А>>
Ytz>Наводящий вопрос — m_some_member_string член базового класса?
Нет. Хотя базовый класс есть, но m_some_member_string объявлен пиватом именно в этом классе в котором и делается вызов.
Здравствуйте, okman, Вы писали:
O>Здравствуйте, Аноним, Вы писали:
А>>У кого есть какие мнения как ловить багу. А>>Я склоняюсь все таки в сторону что кто-то херит память... но как ловить ?
O>Последний раз я встречал точно такую же ошибку (и тоже проявлялось на std::string) в O>одной библиотеке для разбора JSON. Там в целях экономии оперативки предлагалось O>пожертвовать выравниванием данных — в результате кое-где проскакивали экземпляры O>строки, выравненные абы как. Точнее говоря, никак не выравненные. O>В результате программа падала на строке типа std::string Str1 = Str2 + Str3.
Интересная мысль, сделаю щаз ревизию выравниваний.
Хотя с бага с выравниваниями могла бы сразу проявится по идее...
Здравствуйте, ononim, Вы писали:
А>>У кого есть какие мнения как ловить багу. А>>Я склоняюсь все таки в сторону что кто-то херит память... но как ловить ? O>Поставить break on write access (ba w в widbg) на это поле строки когда оно валидно и ждать пока его кто-нить расхерачит. Если строка конечно не меняется часто.
Хорошая мысля!поставлю брекпоинт с кондишином, чой это(с) я сам не догадался
Здравствуйте, kuzya_mil, Вы писали:
Ytz>>Наводящий вопрос — m_some_member_string член базового класса? _>Нет. Хотя базовый класс есть, но m_some_member_string объявлен пиватом именно в этом классе в котором и делается вызов.
Сделай его членом базового класса и проверь все ли в порядке.
Здравствуйте, kuzya_mil, Вы писали:
_>Не могу. Функция вызывается из другой функции та из другой и т.д. _>Могу сказать только что этот код работает долго (несколько часов) и вызывается тысячи раз, после чего происходит эта шляпка. _>Переменная которая передается по ссылке создается на стеке на 6 шесть вызовов вверх по стеку, и она точно целая и невредимая. В отладчике это хорошо видно. _>Переменная в которую делается присваивание (переменная член) — создается вместе с экземпляром класса.
Отладчик может показывать что угодно, примеры тут уже были.
Неплохо пройтись отладчиком по ассемблерному коду, с проверка значений регистров и памяти.