Re[2]: Разрушился стек в приложении на Qt
От: Zhendos  
Дата: 17.08.17 13:57
Оценка: 1 (1)
Здравствуйте, Кузнец, Вы писали:


К>PS. Valgrind запустить можно было, но он бы искал проблему 2-3 дня минимум, и не факт что нашёл бы, так как приложение очень тяжёлое по ресурсам, а падение было далеко не при запуске, в итоге пока valgrind дочапает до проблемного места, пройдёт немало времени, а то и вообще комп не выдержал бы... Поэтому искал без него.


Так поэтому и нужно sanitizer использовать, он на порядок быстрее за счет того,
что выполняется не на аналоге виртуальной машины (valgrind), а напрямую на процессоре,
не даром ребята из google эти santizer сделали.
Re: Разрушился стек в приложении на Qt
От: uzhas Ниоткуда  
Дата: 16.08.17 09:03
Оценка: :)
Здравствуйте, Кузнец, Вы писали:

К>9 ?? 0x10101010101


красиво, поздравляю
Re: Разрушился стек в приложении на Qt
От: Videoman Россия https://hts.tv/
Дата: 16.08.17 10:00
Оценка: +1
Здравствуйте, Кузнец, Вы писали:

К>Проблема сложная. Посоветуйте, что можно пытаться искать? Что ковырять? Думал где-то переполнился стек, но это сомнительно — повышал размер до 128 мб (штатный стек у нас 8 мб), ошибка не ушла.


Если сразу после return все ломается, значит вы внутри функции "проехались" по стеку и возврат происходит в случайное место. this может быть в регистре и также быть не правильно восстановлен из стека. Стеки у потоков разнесены, по-этому, с большой вероятностью, проблема где-то рядом с тем местом, где return. Падение, также, может быть связано с многопоточностью и синхронизацией, но тогда, обычно, проявляется в разных местах, а не в одном и том же, как у вас.
Re: Разрушился стек в приложении на Qt
От: uzhas Ниоткуда  
Дата: 16.08.17 10:43
Оценка: +1
Здравствуйте, Кузнец, Вы писали:

К>Посоветуйте, что можно пытаться искать?


ищи багу в коде
Re: Разрушился стек в приложении на Qt
От: Mr.Delphist  
Дата: 16.08.17 13:43
Оценка: +1
Здравствуйте, Кузнец, Вы писали:

К>Проблема сложная. Посоветуйте, что можно пытаться искать? Что ковырять? Думал где-то переполнился стек, но это сомнительно — повышал размер до 128 мб (штатный стек у нас 8 мб), ошибка не ушла.


Недавно ловил похожее. Причина: мой код звал либу, эта либа делала memcpy() для клонирования одной структуры. Беда была в том, что мой код юзал старые хидеры либы, поэтому аллоцировал меньший размер. А либа в тот день была сбилжена новая, при копировании ориентировалась на свои свежие хидеры, с которыми собрана. В результате скопировала с частичным затиранием дальнейшей части стека (благо у меня там лежал индекс для обращения к массиву, и при затирании туда залилось здоровое число, которое практически тут же ассёртнул эррэй-гвард).
Re: Разрушился стек в приложении на Qt
От: MasterZiv СССР  
Дата: 16.08.17 14:01
Оценка: +1
Здравствуйте, Кузнец, Вы писали:

Ну и конечно, если это возможно, запусти приложение в valgrind.
Re[2]: Разрушился стек в приложении на Qt
От: alex_mah Россия www.elsy.ru
Дата: 16.08.17 20:45
Оценка: +1
Здравствуйте, MasterZiv, Вы писали:

MZ>Здравствуйте, Кузнец, Вы писали:


MZ>Ну и конечно, если это возможно, запусти приложение в valgrind.


По-моему, это первое, что нужно попытаться сделать.
valgrind, memcheck, codeguard и т.д.
Разрушился стек в приложении на Qt
От: Кузнец Россия  
Дата: 16.08.17 08:40
Оценка:
Приложение в Qt, довольно большое, многопоточное (40+ разных нитей). Словили сегфолт, долго ловил, в итоге слёт удалось стабилизировать и локализовать.

В момент слёта оказался уничтожен стек вызовов, выглядел пример так:

0    CGF::check        cgf.cpp    3216    0x4e8f80    
1    ??            0xe500000007000000    
2    ??            0x5d0000000800001a    
3    ??            0x800001c    
4    ??            0x6000000000000000    
5    ??            0x100007fff84f525    
6    ??            0x2e00007fffbb614e    
7    ??            0x9800000000004e8f    
8    ??            0xa001007fff84f527    
9    ??            0x10101010101    
10    ??            0x400000000100114b    
11    ??            0x800000000000ace3    
12    ??            0x6000007fff90d570    
13    ??            0x800007fff84f525    
14    ??            0xc00000000000d687    
15    ??            0x300000000800aabf    
16    ??            0xb00000000000d8dc    
17    ??            0xd800000000023d2e    
18    ??            0xc80000000000d689    
19    ??            0x3e00007fff84f527    
20    ??            0x5800000000004e08    
21    ??            0x10000000000aaa7    
22    ??            0x900007fffbb6155    
23    ??            0x4e8c    
24    ??            0x10000000041c800    
25    ??            0x8000010101010101    
26    ??            0x6000007fff90d570    
27    ??            0x5000007fff84f525    
28    ??            0xa00000000000a905    
29    ??            0x10000000000d517    
30    ??


Класс, функции которого вызывались, оказался также уничтожен, в отладчике его поля все показывались как <недоступно>, также поменялся адрес this.

Поиск момента, в который произошло разрушение стека и this'а дал следующее:

int MyClass::Foo(int arg)
{
    ...
    return return_value;
}

void MyClass::Foo2()
{
    ...
    Foo(i);
    int v = 0;
}


В момент return return_value; в функции Foo() стек и this были ещё целы (точка останова на return'е), сразу после выхода из функции, в точке останова на int v = 0;, стек уже убит (как и this).

Выглядит так, будто где-то случилось переполнение стековых массивов и в итоге перетёрлись адреса возврата, плюс произошёл сдвиг адреса this. Попробую ещё вручную исправить адрес this'а, вычислив величину смещения, позже напишу, что получилось.

Проблема сложная. Посоветуйте, что можно пытаться искать? Что ковырять? Думал где-то переполнился стек, но это сомнительно — повышал размер до 128 мб (штатный стек у нас 8 мб), ошибка не ушла.
Re: Разрушился стек в приложении на Qt
От: Кузнец Россия  
Дата: 16.08.17 08:52
Оценка:
Сравнил адреса до и после разрушения, после разрушения адрес this либо вообще отсутствовал (в отладчике было пустое поле), либо становился равным 0x500000000000ace3.
Re: Разрушился стек в приложении на Qt
От: SaZ  
Дата: 16.08.17 08:58
Оценка:
Здравствуйте, Кузнец, Вы писали:

К>Приложение в Qt, довольно большое, многопоточное (40+ разных нитей). Словили сегфолт, долго ловил, в итоге слёт удалось стабилизировать и локализовать.

К>В момент слёта оказался уничтожен стек вызовов, выглядел пример так:
К>...

А не может быть того, что в одном потоке идёт вызов метода, а в другом в этот момент класс уничтожается? Класс точно спроектирован, как потокобезопасный?
Re: Разрушился стек в приложении на Qt
От: Zhendos  
Дата: 16.08.17 09:37
Оценка:
Здравствуйте, Кузнец, Вы писали:

К>Приложение в Qt, довольно большое, многопоточное (40+ разных нитей). Словили сегфолт, долго ловил, в итоге слёт удалось стабилизировать и локализовать.


К>В момент слёта оказался уничтожен стек вызовов, выглядел пример так:



К>Выглядит так, будто где-то случилось переполнение стековых массивов и в итоге перетёрлись адреса возврата, плюс произошёл сдвиг адреса this. Попробую ещё вручную исправить адрес this'а, вычислив величину смещения, позже напишу, что получилось.


К>Проблема сложная. Посоветуйте, что можно пытаться искать? Что ковырять? Думал где-то переполнился стек, но это сомнительно — повышал размер до 128 мб (штатный стек у нас 8 мб), ошибка не ушла.


А Address / Memory / Thread Sanitizer никаких ошибок не находят?
Re: Разрушился стек в приложении на Qt
От: Chorkov Россия  
Дата: 16.08.17 10:23
Оценка:
Здравствуйте, Кузнец, Вы писали:


К>Поиск момента, в который произошло разрушение стека и this'а дал следующее:


К>
К>int MyClass::Foo(int arg)
К>{
К>    ...
К>    return return_value;
К>}

К>void MyClass::Foo2()
К>{
К>    ...
К>    Foo(i);
К>    int v = 0;
К>}
К>


К>В момент return return_value; в функции Foo() стек и this были ещё целы (точка останова на return'е), сразу после выхода из функции, в точке останова на int v = 0;, стек уже убит (как и this).


Похоже, при выполнении деструкторов локальных переменных MyClass::Foo кто-то расстрелял память, повредив стек ниже себя.
В результате поврежден указатель на точку вызова функции (куда возвращаться по return).

Есть ли там объекты с нетривиальными деструкторами?
Объекты стандартной библиотеки (std::string, std::vector) тоже могут расстрелять память в деструкторе, если находятся в несогласованном состоянии (т.е. кто-то предварительно расстрелял их самих).

Если падение воспроизводится в отладчике, то находясь в точке останова на return, в деструкторы локальных объектов можно зайти командой "Step into (F11)", или поставить точки останова на места объявления локальных переменных...

Если в отладчике не воспроизводится, проверить гипотизу можно добавив буфер:
int MyClass::Foo(int arg)
{
    char bufer[1024];
    ...
    return return_value;
}

Расстрел памяти, с высокой вероятностью, придется на него, а не на системную информацию на стеке.
Re: Разрушился стек в приложении на Qt
От: AleksandrN Россия  
Дата: 16.08.17 10:37
Оценка:
Здравствуйте, Кузнец, Вы писали:

К>Проблема сложная. Посоветуйте, что можно пытаться искать? Что ковырять? Думал где-то переполнился стек, но это сомнительно — повышал размер до 128 мб (штатный стек у нас 8 мб), ошибка не ушла.


Версии:
1. memcpy куда-то не туда или не того размера. Посмотри на работу с массивами и на выравнивание данных в структурах.
2. Неинициализированные переменные (или наоборот — указатель инициализирован неправильным значением).
3. использование функций printf, sprintf и т.п., но спецификаторы не соответствуют данным, из-за этого портится стек.

Если проблема повторяется — скорее всего портится стек в этом потоке. Иначе — ошибка может быть в любом другом потоке и проявится в другом месте.
Отредактировано 16.08.2017 10:54 AleksandrN . Предыдущая версия .
Re: Разрушился стек в приложении на Qt
От: MasterZiv СССР  
Дата: 16.08.17 13:59
Оценка:
Здравствуйте, Кузнец, Вы писали:

К>Проблема сложная. Посоветуйте, что можно пытаться искать? Что ковырять? Думал где-то переполнился стек, но это сомнительно — повышал размер до 128 мб (штатный стек у нас 8 мб), ошибка не ушла.


Надо понимать, что то, что программа где-то падает в каком-то конкретном месте, не обязательно означает, что это место программы как-то связано с причиной этого падения.
Прежде всего, нужно собрать debug info, чтобы было куда глянуть при случае.

Далее, если ты знаешь, как проблему воспроизвести, собери отладочную версию (без оптимизации), и попробуй воспроизвести там.
Если воспроизведётся -- будет гораздо легче.
Re: Разрушился стек в приложении на Qt
От: Кузнец Россия  
Дата: 17.08.17 12:15
Оценка:
Спасибо за полезные ответы. Почти всё было применено, в итоге проблему нашли. Всё оказалось просто до безобразия — в одном месте, вообще другом, залезли вне диапазона двумерного массива, который был размещён на стеке, чаще всего это портило лишь немного данных, но при определённых условиях это разрушало стек, в итоге программа начинала работать (почти) непредсказуемо, и падала вообще в другом месте.

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

Итог: программа падала в некотором месте, потому что был убит стек во втором месте (совершенно далёком от первого), а стек был убит по причине ошибки в третьем месте (ещё более далёком).

Нашли это безобразие аккуратным анализом хода выполнения программы (пока анализировал простыни чужого кода, не раз проклял break/continue, применяемые везде, где только возможно, ибо шагание по точкам останова в таком коде так себе удовольствие). Что забавно, фикс ошибки — изменение одной буквы во всём коде проекта

А ошибка была при копипасте (которую, к слову, делал не я), в последней строке поменяли dR на dB во всех местах, кроме одного.

Мораль — если копипастите, внимательно проверяйте результат, и особенно последнюю сточку.

PS. Valgrind запустить можно было, но он бы искал проблему 2-3 дня минимум, и не факт что нашёл бы, так как приложение очень тяжёлое по ресурсам, а падение было далеко не при запуске, в итоге пока valgrind дочапает до проблемного места, пройдёт немало времени, а то и вообще комп не выдержал бы... Поэтому искал без него.
Re[3]: Разрушился стек в приложении на Qt
От: Кузнец Россия  
Дата: 17.08.17 14:10
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Так поэтому и нужно sanitizer использовать, он на порядок быстрее за счет того,

Z>что выполняется не на аналоге виртуальной машины (valgrind), а напрямую на процессоре,
Z>не даром ребята из google эти santizer сделали.

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

На них есть русскоязычная документация? А то я пока только английскую нашёл (https://github.com/google/sanitizers/wiki).
Re[4]: Разрушился стек в приложении на Qt
От: Zhendos  
Дата: 17.08.17 15:07
Оценка:
Здравствуйте, Кузнец, Вы писали:

К>Здравствуйте, Zhendos, Вы писали:


Z>>Так поэтому и нужно sanitizer использовать, он на порядок быстрее за счет того,

Z>>что выполняется не на аналоге виртуальной машины (valgrind), а напрямую на процессоре,
Z>>не даром ребята из google эти santizer сделали.

К>Спасибо, попробую разобраться с ними, если они и правда шустрее и также эффективны, то лучше работать с ними.


К>На них есть русскоязычная документация? А то я пока только английскую нашёл (https://github.com/google/sanitizers/wiki).


Не знаю насчет русской документации, но к ним особая документация
и не нужна добавляете например -fsanitize=address в опции gcc/clang
пересобираете свое приложение и запускаете, если что не так
приложение упадет и в стандартный stdout/stderr напишет что и почему,
так же другие sanitizer подключаются. Возможно man gcc или man clang
есть на русском.
Re[5]: Разрушился стек в приложении на Qt
От: Кузнец Россия  
Дата: 18.08.17 06:06
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Не знаю насчет русской документации, но к ним особая документация

Z>и не нужна добавляете например -fsanitize=address в опции gcc/clang
Z>пересобираете свое приложение и запускаете, если что не так
Z>приложение упадет и в стандартный stdout/stderr напишет что и почему,
Z>так же другие sanitizer подключаются. Возможно man gcc или man clang
Z>есть на русском.

В Qt в pro файлы добавил:

QMAKE_CFLAGS += -fsanitize=address
QMAKE_LFLAGS += -fsanitize=address


Собрался в релизе — вывод от санитайзера был, в дебуге ни в какую не хочет, где я мог накосячить?
Отредактировано 18.08.2017 6:08 Кузнец . Предыдущая версия .
Re[6]: Разрушился стек в приложении на Qt
От: Кузнец Россия  
Дата: 18.08.17 07:08
Оценка:
Здравствуйте, Кузнец, Вы писали:

К>В Qt в pro файлы добавил:


К>
К>QMAKE_CFLAGS += -fsanitize=address
К>QMAKE_LFLAGS += -fsanitize=address
К>


К>Собрался в релизе — вывод от санитайзера был, в дебуге ни в какую не хочет, где я мог накосячить?


В дебуге тоже удалось получить вывод, но почему-то он не отличается от вывода в релизе, видимо санитайзер не умеет показывать место в коде, где произошла ошибка, только функцию. Но всё равно интересная штука.
Re[7]: Разрушился стек в приложении на Qt
От: Кузнец Россия  
Дата: 18.08.17 07:31
Оценка:
А memory sanitizer что-то не получается подключить, задал флаги Qt:

QMAKE_CXXFLAGS += -fsanitize=memory
QMAKE_LFLAGS += -fsanitize=memory

QMAKE_CXXFLAGS += -fPIE
QMAKE_LFLAGS += -fPIE

QMAKE_CXXFLAGS += -pie
QMAKE_LFLAGS += -pie


и получил ошибку:

error: unrecognized argument to -fsanitize= option: 'memory'
Re[7]: Разрушился стек в приложении на Qt
От: Zhendos  
Дата: 18.08.17 08:33
Оценка:
Здравствуйте, Кузнец, Вы писали:

К>Здравствуйте, Кузнец, Вы писали:


К>>Собрался в релизе — вывод от санитайзера был, в дебуге ни в какую не хочет, где я мог накосячить?


К>В дебуге тоже удалось получить вывод, но почему-то он не отличается от вывода в релизе, видимо санитайзер не умеет показывать место в коде, где произошла ошибка, только функцию. Но всё равно интересная штука.


Вы что-то на него наговариваете, у него очень подробный вывод
вплоть до переменных, например:

int main() {
        int arr[5];
        arr[5] = 17;
        return 0;
}


Как видите и строчки кода показывает и даже имя переменной:
==28730==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffdfbf6e3b4 at pc 0x00472c2e3a15 bp 0x7ffdfbf6e370 sp 0x7ffdfbf6e360
WRITE of size 4 at 0x7ffdfbf6e3b4 thread T0
    #0 0x472c2e3a14 in main /tmp/a.c:3
    #1 0x7f2f88ce44c9 in __libc_start_main (/usr/lib/libc.so.6+0x204c9)
    #2 0x472c2e3859 in _start (/tmp/a.out+0x859)

Address 0x7ffdfbf6e3b4 is located in stack of thread T0 at offset 52 in frame
    #0 0x472c2e3949 in main /tmp/a.c:1

  This frame has 1 object(s):
    [32, 52) 'arr' <== Memory access at offset 52 overflows this variable


К>>В Qt в pro файлы добавил:

К>>
К>>QMAKE_CFLAGS += -fsanitize=address
К>>QMAKE_LFLAGS += -fsanitize=address
К>>


Вроде бы правильный вариант это через CONFIG,
поддержка sanitizer интегрирована в Qt:

CONFIG += sanitizer sanitize_address


но я сам использую cmake, поэтому "за что купил, за то продал"
Re[8]: Разрушился стек в приложении на Qt
От: Zhendos  
Дата: 18.08.17 08:35
Оценка:
Здравствуйте, Кузнец, Вы писали:

К>А memory sanitizer что-то не получается подключить, задал флаги Qt:


К>
К>QMAKE_CXXFLAGS += -fsanitize=memory
К>QMAKE_LFLAGS += -fsanitize=memory

К>QMAKE_CXXFLAGS += -fPIE
К>QMAKE_LFLAGS += -fPIE

К>QMAKE_CXXFLAGS += -pie
К>QMAKE_LFLAGS += -pie
К>


К>и получил ошибку:


К>
К>error: unrecognized argument to -fsanitize= option: 'memory'
К>


Ну clang и gcc все-таки разные компиляторы, поэтому хотя команда Google
и работала над внедрением sanitizer для обоих компиляторов, но интерфейс
не точно соотвествует, -fsanitize=memory это только для clang,
точный список опций можно посмотреть в man gcc
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.