Условная точка останова GDB в многопоточном приложении - PullRequest
0 голосов
/ 17 января 2020

Я использую gdb для отладки многопоточной программы.

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

В этом l oop , Я буду sh прерывать, если строка в любом из этих потоков равна предопределенной константной строке. Для этого я использую break myfile:1234 if $_streq(managedStr->value(), "testString").

Но эта точка останова никогда не срабатывает, хотя я точно знаю, что managestStr наверняка принимает значение "testString".

При выходе из условия, он ломается, но при попытке вручную оценить условие, я получаю сообщение об ошибке

Программа остановилась в другом потоке во время вызова функции из GDB.

Из эта ссылка Я научился устанавливать опцию scheduler-locking, пока программа находится в режиме паузы, но установка этой опции с самого начала не помогла, чтобы точка останова не была нажата. Вместо этого он получит get

Ошибка при тестировании состояния точки останова: программа остановилась в другом потоке во время вызова функции из GDB. Оценка выражения, содержащего функцию (ManageString :: value ()), будет прекращена. Когда функция будет выполнена, GDB автоматически остановится. [Переключение на поток 0x7ffd35fb3700 (LWP 24354)]

Что я могу сделать, чтобы добиться желаемого поведения?

1 Ответ

1 голос
/ 17 января 2020

break myfile:1234 if $_streq(managedStr->value(), "testString")

То, что должно работать, и тот факт, что он не работает, означает ошибку в GDB.

То Сказал, что этот метод отладки чрезвычайно медленный, потому что GDB должен остановить каждый поток в строке 1234 и затем проверить значения памяти (то есть оценить условие).

Обычно это намного быстрее, чтобы вставить немного вспомогательный код в программе:

if (strcmp(namagedStr->value(), "testString") == 0) {
  printf("DEBUG: match\n");  // set breakpoint here!
}

и перестройте его.

Теперь вместо того, чтобы постоянно останавливать каждый поток и оценивать условие, GDB установит точку останова для кода, равную только достигается, когда условие истинно. Это будет в 100-1000 раз быстрее (в зависимости от количества потоков).

Эта техника может быть тривиально расширена, если вам нужно варьировать фактическое значение, которое вы ищете, от запуска к запуску или даже в пределах одного запустить, добавив глобальную переменную:

const char *str_to_match = "testString";  // variable can be overwritten in GDB


    if (strcmp(managedStr->value(), str_to_match) == 0) {
      ...
    }
...