Инструменты для изоляции ошибки разбивки стека

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

У меня очень многопоточная программа (pthreads) C/С++, которая разработала проблему разбивки стека под оптимизированными компиляторами с GCC после 4.4.4 и до 4.7.1.

Симптом заключается в том, что во время создания одного из потоков я получаю полный стек, а не только% RIP, но все родительские кадры и большинство регистров являются 0x00 или другим нечувствительным адресом. Какой поток вызывает проблему, кажется, случайным, однако, судя по сообщениям журнала, он кажется изолированным от одного и того же кодового кода и, кажется, приходит в полу повторяемую точку при создании нового потока.

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

Создание потока, которое выводит поток, который в конечном итоге разбивает стек:

 
extern "C"
{
static ThreadReturnVal ThreadAPI WriterThread(void *act)
{
   Recorder       *rec = reinterpret_cast  (act);
   xuint64        writebytes;
   LoggerHandle m_logger = XXGetLogger("WriterThread");

   if (SetThreadAffinity(rec->m_cpu_mask))
   { ... }
   SetThreadPrio((xint32)rec->m_thread_priority);

   while (true)
   {
     ... poll a ring buffer ... Hard Spin 100% use on a single core, this is that sort of crazy code. 
   }
}

Я пробовал сборку отладки, но симптом присутствует только в оптимизированных сборках, -O2 или выше. Я пробовал Valgrind/memcheck и DRD, но оба не смогли найти какую-либо проблему до того, как стек сдулся (и для достижения сбоя потребуется около 12 часов).

Компиляция с -O2 -Wstack-protector не видит ничего плохого,  однако сборка с -fstack-protector - все это защитит меня от ошибки, но не испугает ошибок.

Электрический забор также ловушки, но только после того, как стек ушел.

Вопрос: Какие другие инструменты или методы будут полезны для сужения раздела о нарушении?

Большое спасибо, --Bill

Ответы

Ответ 1

Несколько вариантов для решения этой проблемы:

Вы можете попытаться установить контрольную точку аппаратного обеспечения на адрес стека до того, как произойдет повреждение, и надейтесь, что отладчик достаточно рано сломается в коррупции, чтобы обеспечить смутно полезное состояние отладки. Трудная часть здесь - выбор правильного адреса стека; в зависимости от того, насколько случайным является "выбор" оскорбительной нити, это может быть непрактично. Но из одного из ваших комментариев это звучит так, будто часто создаваемый поток разбивается, поэтому это может быть выполнимо. Попытайтесь сломаться во время создания потока, захватите местоположение стека потоков, сметете на какую-то дикую догадку, установите аппаратное BP и продолжайте. Исходя из того, ломаетесь ли вы слишком рано, слишком поздно или совсем нет, отрегулируйте смещение, полоскание и повторите. Это, в основном, предварительная догадка и проверка, и она может быть сильно затруднена или совершенно непрактична, если шаблон коррупции слишком случайный, но удивительно, как часто это может привести к полуразборчивому стеку и успешным усилиям по отладке.

Другой вариант - начать сбор дампов аварий. Попробуйте найти шаблоны между дампами сбоев, которые могут помочь вам приблизиться к источнику коррупции. Возможно, вам повезет, и одна из аварийных дампов столкнется "быстрее" / "ближе к источнику".

К сожалению, обе эти технологии - больше искусства, чем наука; они не детерминированы, полагаются на здоровую дозу удачи и т.д. (по крайней мере, на моем опыте... что, как говорится, есть люди, которые могут делать удивительные вещи со свалками, но это занимает много времени чтобы достичь этого уровня мастерства).

Еще одна сторона примечания: как указывали другие, неинициализированная память является очень типичным источником отладочных версий vs release и может быть легко вашей проблемой. Однако, еще одна возможность иметь в виду разницу во времени. Порядок, в котором потоки планируются и долгое время, часто резко отличается от debug vs release и может легко привести к ошибкам синхронизации, которые маскируются в одном, но не в другом. Эти различия могут быть вызваны различиями в скорости выполнения, но я думаю, что некоторые временные ряды преднамеренно нарушают планирование потоков в среде отладки.

Ответ 2

Вы можете использовать инструмент статического анализа, чтобы проверить некоторые ошибки sutble, возможно, одна из найденных ошибок станет причиной вашей ошибки. Вы можете найти информацию об этих инструментах здесь.