2014-10-26 2 views
0

Я новичок в GDB и не уверен, что кто-то из вас испытал: когда я использовал GDB для отладки программы с двумя потоками, я нашел выполнение шаговой линии на линия не является линейной или непредсказуема даже для одного потока, а распечатанное значение переменной также запутывает. Скажем, у меня есть программа (в C++) выглядит так:GDB Отладка многопоточности, выполнение непредсказуемо для одиночного потока

(Я отлаживаю командную строку ubuntu, используя режим gdb -tui).

..... 
    70 for (int i = 0; i < MAX; i++) { 
    71  int foo = 1; 
b+ 72  Bar *bar = f1(); 
    73  int v1 = bar->doCalc(); 
    74  int v2 = bar->get(foo); 
    75 } 
..... 

В начале, программа остановилась на line 72, то я ступил построчно, пока она не достигнет line 74. В этот момент я распечатал значение v1, но, похоже, эта переменная все еще не имеет значимого значения. Затем, если я наберу «следующий», выполнение программы снова вернется к line 72 !! Это первое, что вызвало мое замешательство. Затем я продолжаю переход к следующей строке, пока не достигнет line 74. В этот момент я распечатал v1, и на этот раз он имеет какое-то значимое значение. Я дважды проверил итератор i, его значение одно и то же, что означает, что оно находится в одном и том же i-м выполнении одного цикла. Я смущен, как это может произойти? Может ли кто-нибудь помочь мне? Спасибо!

+1

Вы оптимизировали оптимизацию компилятора, да? –

+1

При отладке многопоточных приложений часто лучше постоянно устанавливать точки останова на следующей строке, а не пытаться делать одношаговые. Одноступенчатый часто приводит к тому, что «следующий шаг» переходит к несвязанному коду, поскольку код, который вы использовали, делает syscall. Конечно, если у вас несколько потоков, работающих по одному и тому же коду, это еще более запутанно - команда с одним шагом иногда заставляет казаться, что код бежит назад :) –

+0

Это кажется очень мало связанным с несколькими потоками, и все, что связано с компилятором оптимизаций. Для начала 'foo' фактически не нужно быть переменной; 'i' может быть полностью оптимизирован (или может обновляться только каждые итераций из-за разворачивания). Переменные назначения не должны быть в порядке; 'v1' и' v2' фактически не должны существовать или быть назначены вообще! –

ответ

0

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

Многопоточность вряд ли будет иметь какое-либо отношение к вашей проблеме (хотя она представляет свои проблемы при одношаговом режиме). IF многопоточность влияет на вашу отладку, вы должны видеть сообщения в GDB, такие как [Switching to Thread 0x7ffff61ec700 (LWP 21427)], когда выполнение переключается с одного потока на другой.

+0

Большое спасибо. Это связано с тем, что код был оптимизирован при компиляции. Я использовал 'CMake' для создания Makefile. И я использовал флаг RelWithDebInfo для компилятора, который в соответствии с тем, что я нашел, означает: _ompiler flags для компиляции сборки релиза с флагами отладки из C sources_. Поэтому я предполагаю, что он все еще более или менее оптимизирован для выполнения. Затем я сменил флаг на '-DCMAKE_BUILD_TYPE = Debug', теперь он работает как шарм. – Dreamer

Смежные вопросы