Да, это звучит как состояние гонки или повреждение кучи или что-то еще, что обычно отвечает за Гейзенбагов.Проблема в том, что ваш код в некотором месте, вероятно, неверен, но отладчик должен вести себя, даже если отлаженное приложение делает забавные вещи.Таким образом, проблемы, как правило, исчезают при отладчике.А для условий гонки они часто не появляются в первую очередь, потому что некоторые отладчики могут обрабатывать только один поток за раз, и равномерно все отладчики заставят код работать медленнее, что может уже привести к исчезновению условий гонки.
Попробуйте Valgrind в приложении.Поскольку вы используете MinGW, есть вероятность, что ваше приложение будет компилироваться в среде, в которой может работать Valgrind (даже если он не запускается непосредственно в Windows).Я использую Valgrind уже около трех лет, и он быстро разгадал множество загадок.Первое, когда я получу отчет о сбое в коде, с которым я работаю (который работает на AIX, Solaris, BSD, Linux, Windows), я собираюсь сделать один тестовый запуск кода под Valgrind в x64 и x86 Linuxсоответственно.
Valgrind, и в вашем конкретном случае его инструмент по умолчанию Memcheck, будет эмулировать код.Всякий раз, когда вы выделяете память, она будет помечать все байты в этой памяти как «испорченные», пока вы не инициализируете ее явно.Загрязненное состояние байтов памяти будет унаследовано неинициализированной памятью memcpy
и приведет к отчету от Valgrind, как только неинициализированный байт будет использован для принятия решения (if
, for
, while
...).Кроме того, он отслеживает потерянные блоки памяти и сообщит об утечках в конце цикла.Но это еще не все, больше инструментов являются частью семейства Valgrind и тестируют различные аспекты вашего кода, включая условия состязания между потоками (Helgrind, DRD).
Предполагая, что Linux сейчас: убедитесь, что у вас есть все отладкисимволы ваших вспомогательных библиотек установлены.Обычно они входят в *-debug
версию пакетов или *-devel
.Также обязательно отключите оптимизацию в своем коде и включите символы отладки.Для GCC это -ggdb -g3 -O0
.
Еще один совет: у меня было то, что наложение указателей вызвало некоторое горе.Хотя Valgrind смог помочь мне отследить его, мне фактически пришлось сделать последний шаг и проверить созданный код при его разборке.Оказалось, что на -O3
оптимизатор GCC опередил себя и превратил цикл копирования байтов в последовательность инструкций для одновременного копирования 8 байтов, но предполагал выравнивание .Последняя часть была проблемой.Предположение о выравнивании было неверным.С тех пор мы начали строить на -O2
- что, как вы увидите в этой статье Gentoo Wiki , не является худшей идеей.Процитируем соответствующую часть…
-O3: это максимально возможный уровень оптимизации, а также самый рискованный.Скомпилирование вашего кода с этой опцией займет больше времени, и фактически его не следует использовать для всей системы с gcc 4.x.Поведение gcc значительно изменилось с версии 3.x.В 3.x было показано, что -O3 приводит к немного более быстрому времени выполнения по сравнению с -O2, но это больше не относится к gcc 4.x.Компиляция всех ваших пакетов с -O3 приведет к большим бинарным файлам, которые требуют больше памяти, и значительно увеличит шансы сбоя компиляции или неожиданного поведения программы (включая ошибки).Недостатки перевешивают выгоды;помните принцип убывающей отдачи.Использование -O3 не рекомендуется для gcc 4.x.
Поскольку вы используете GCC в MinGW, я считаю, что это вполне может относиться и к вашему делу.