LINUX.ORG.RU

Странный segfault

 , ,


0

3

Пытаюсь найти причину сегфолта в приложении (linux, x86). gdb показывает что падает внутри wstringstream::operator<<(). Грубо говоря, соответствующий фрагмент функции выглядит так:

  char* buff = new char[size];
  // заполняем buff и за его границы точно нигде не выходим
  ...
  std::wstringstream wss;
  wss << buff;
При len > ~500000 падает всегда. Первая мысль что где-то повреждается память, но анализ кода ничего не дал.

Затем попробовал запустить под valgrind'ом и получил «Invalid write of size 4» внутри wstringstream::operator<<() и дальше мол адрес принадлежит стеку треда X.

После этого решил проанализировать стек в gdb после сегфолта и вот здесь обнаружил что при вызове wstringstream::operator<<() регистр esp уменьшился на ~2000000, а в этом стековом фрейме лежит wchar_t-представление buff. Иначе говоря выглядит будто wstringstream::operator<<() преобразовал buff из char[] в wchar_t[] прямо на стеке и тем самым вышел за его пределы. Как-то мне совсем не верится что std::wstringstream выполняет преобразование на стеке, а не в динамической памяти. Может у кого какие соображения есть по этому поводу?

PS: я понимаю что следующим шагом должен быть анализ wstringstream::operator<<(), но для этого нужно иметь либо его исходники которых на данный момент у меня нет (известно что конечное приложение собирали gcc, а вот какой именно версией пока выяснить не удалось) либо ковыряться с ассемблерным кодом на что у меня желания нет



Последнее исправление: ricie (всего исправлений: 2)

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

anonymous
()

Попробуй по тупому, в цикле небольшими порциями скармливать buff wstringstream'у. Посмотри что получится.

WRG ★★★★
()
Ответ на: комментарий от anonymous

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

Никто и не просит гадать, прошу поделиться соображениями (если они конечно есть). Фрагмент кода в котором падает локализован, условие падения тоже известно (len >~ 500000).

ricie
() автор топика
Ответ на: комментарий от ricie

Никто и не просит гадать, прошу поделиться соображениями (если они конечно есть). Фрагмент кода в котором падает локализован, условие падения тоже известно (len >~ 500000).

При работе с памятью локализация падения(и условие) не всегда означает, что память портится именно из-за этого кода.

Сделай минимальный работающий пример и кинь его сюда.

anonymous
()
Ответ на: комментарий от WRG

Попробуй по тупому, в цикле небольшими порциями скармливать buff wstringstream'у. Посмотри что получится.

Пересобрать само приложение я не могу т.к. у меня нет его исходников (мы предоставляем третьей стороне исходный код, который они и включают в свое приложение). Разве что написать свое тестовое приложение, но не факт что оно упадет.

ricie
() автор топика
Ответ на: комментарий от anonymous

Это опечатка в посте. Поправил.

ricie
() автор топика
Ответ на: комментарий от ricie

Пересобрать само приложение я не могу т.к. у меня нет его исходников (мы предоставляем третьей стороне исходный код, который они и включают в свое приложение). Разве что написать свое тестовое приложение, но не факт что оно упадет.

Так пусть и отлаживают... Или попроси их пересобрать. Или прислать скрипты сборки... Пусть хотя бы дебажную информацию включат, а то на регистры смотреть в таком деле штука неблагодарная.

anonymous
()
Ответ на: комментарий от ricie

Насколько ты уверен, что приведенный тобой фрагмент кода, соответствует исходному коду того места, где происходит падение? Может это твои ..эм.. «партнеры» нахреначили?

anonymous
()
Ответ на: комментарий от ricie

Ну, так если не упадет, значит проблема не здесь, а где-то еще. Табе же чувак об этом сказал.

При работе с памятью локализация падения(и условие) не всегда означает, что память портится именно из-за этого кода.
Сделай минимальный работающий пример и кинь его сюда.

Aswed ★★★★★
()

Все тему можно закрывать. Как оказалось действительно старые версии gcc делают преобразование char[] в wchar_t[] на стеке. Вот кусок кода из соответствующего operator<<() версии 4.1.1:

size_t __clen = __traits_type::length(__s);
_CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
                                                     * __clen));
for (size_t  __i = 0; __i < __clen; ++__i)
  __ws[__i] = __out.widen(__s[__i]);
_CharT* __str = __ws;

А вот этот же кусок кода, но из более поздней версии (__builtin_alloca заменили на new):

const size_t __clen = __traits_type::length(__s);
__ws = new _CharT[__clen];
for (size_t  __i = 0; __i < __clen; ++__i)
  __ws[__i] = __out.widen(__s[__i]);
_CharT* __str = __ws;

ricie
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.