Как создать условную точку останова с помощью std::string

Предположим, у меня есть эта функция:

std::string Func1(std::string myString)
{
   //do some string processing 
   std::string newString = Func2(myString)
   return newString;  
}

как установить условный перерыв, когда newString имеет конкретное значение? (без изменения источника)

установка условия newString == "my value"

не работает точки останова были отключены с ошибкой "перегруженный оператор не найден"

12 ответов

Решение

Некоторым поискам не удалось найти какой-либо способ сделать это. Предлагаемые альтернативы - поместить тест в ваш код и добавить стандартную точку останова:

if (myStr == "xyz")
{
    // Set breakpoint here
}

Или создать свой тест из сравнения отдельных персонажей. Даже смотреть на отдельные символы в строке немного рискованно; в Visual Studio 2005 мне пришлось копаться в переменных-членах, таких как

myStr._Bx._Buf[0] == 'x' && myStr._Bx._Buf[1] == 'y' && myStr._Bx._Buf[2] == 'z'

Ни один из этих подходов не является очень удовлетворительным. У нас должен быть лучший доступ к вездесущей функции Стандартной библиотеки.

В Visual Studio 2010/2012 есть гораздо более простой способ.

Чтобы выполнить то, что вы ищете в ANSI, используйте это:

strcmp(newString._Bx._Ptr,"my value")==0 

И в Unicode (если newString был Unicode) используйте это:

wcscmp(newString._Bx._Ptr, L"my value")==0 

Есть больше вещей, которые вы можете сделать, чем просто сравнение, вы можете прочитать об этом здесь:

http://blogs.msdn.com/b/habibh/archive/2009/07/07/new-visual-studio-debugger-2010-feature-for-c-c-developers-using-string-functions-in-conditional-breakpoints.aspx

В VS2017 я смог установить условие как:

strcmp(&newString[0], "my value") == 0

В VS2017 вы можете сделать

strcmp(newString._Mypair._Myval2._Bx._Buf,"myvalue")==0

VS2012:

Я просто использовал условие ниже, потому что newString._Bx._Ptr (как в ответе OBWANDO) ссылается на незаконную память

strcmp( newString._Bx._Buf, "my value")==0

и это сработало...

Хотя мне приходилось обходить это, используя что-то похожее на ответ Брэда (плюс использование DebugBreak(), чтобы вырваться из кода), иногда редактирование / перекомпиляция / повторный запуск небольшого количества кода либо слишком трудоемки, либо просто невозможны,

К счастью, по-видимому, можно использовать настоящие члены класса std::string. Здесь упоминается об одном способе - и хотя он специально вызывает VS2010, вы все равно можете обращаться к отдельным символам вручную в более ранних версиях. Так что если вы используете 2010, вы можете просто использовать хороший strcmp() функции и тому подобное ( больше информации), но если вы похожи на меня и у вас еще есть версия 2008 или более ранняя, вы можете придумать рваную, ужасную, но функциональную альтернативу, установив условную точку останова, например:

strVar._Bx._Ptr[0] == 'a' && strVar._Bx._Ptr[1] == 'b' &&
   strVar._Bx._Ptr[2] == 'c'

сломать, если первые три символа в strVar - "abc". Вы можете продолжать идти с дополнительными символами, конечно. Ужасно... но это сэкономило мне немного времени.

У @OBWANDO (почти) есть решение, но, как справедливо указывают несколько комментариев, фактический буфер зависит от размера строки; Я вижу 16, чтобы быть порогом. Предварительная проверка размера в strcmp в соответствующем буфере работает.

newString._Mysize < 16 && strcmp(newString._Bx._Buf, "test value") == 0

или же

newString._Mysize >= 16 && strcmp(newString._Bx._Ptr, "ultra super long test value") == 0

Пытался использовать strcmp в gdb8.1 под ubuntu18.04, но это не работает:

(ins)(gdb) p strcmp("a", "b")
$20 = (int (*)(const char *, const char *)) 0x7ffff5179d60 <__strcmp_ssse3>

Согласно этому ответу,strcmp, это специальный IFUNC, можно настроить такое условие:

condition 1 __strcmp_ssse3(camera->_name.c_str(), "ping")==0

Это довольно некрасиво, не хочу делать это второй раз.

Этот ответ дает гораздо лучшее решение, он использует std::string:: compare:

condition 1 camera->_name.compare("ping") == 0

Сравнение строк работает лучше, чем сравнение символов

strcmp(name._Mypair._Myval2._Bx._Buf, "foo")==0

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

name._Mypair._Myval2._Bx._Buf[0] == 'f' && 
name._Mypair._Myval2._Bx._Buf[1] == '0' && 
name._Mypair._Myval2._Bx._Buf[2] == '0'

В VS2015 вы можете сделать

newstring[0]=='x' && newString[1]=='y' && newString[2]=='z'

Вы можете преобразовать его в строку переменного тока, используя c_str() вот так:

$_streq(myStr.c_str(), "foo")

Чтобы установить условную точку останова в std ::string, вам необходимо установить ее на реальных внутренних членах std ::string. То, что вы видите в окне просмотра, упрощено.

Вы можете отобразить реальную структуру переменной в окне просмотра, используя ,!суффикс. В вашем примере:

      newString,!

Для MSVC 2015-2019 вы можете использовать:

Для строки длиной не более 15 символов:

      (newString._Mypair._Myval2._Myres < 16) ?
    strcmp(newString._Mypair._Myval2._Bx._Buf, "short") == 0 : 
    false

Для (даже исторически) более длинных строк:

      (newString._Mypair._Myval2._Myres < 16) ? false : 
     strcmp(newString._Mypair._Myval2._Bx._Ptr, "My_test_str_value_longer_than_16_chars") == 0

Остерегаться:

  • Имя переменной записывается дважды в каждом условии!
  • Вам нужно все выражение в одной строке. Используйте версии для копирования и вставки, указанные ниже.

Универсальное условие требует, чтобы тестовое значение было дважды, а имя переменной - трижды:

      (newString._Mypair._Myval2._Myres < 16) ? 
    strcmp(newString._Mypair._Myval2._Bx._Buf, "My_test_string") == 0 : 
    strcmp(newString._Mypair._Myval2._Bx._Ptr, "My_test_string") == 0

Примечания: используйте wcscmp вместо того strcmp если вы работаете с std::wstring.

Дополнительные сведения об оптимизации небольших строк в C++ https://vorbrodt.blog/2019/03/30/sso-of-stdstring/ включает образец кода для определения размера внутреннего буфера строки.

Все однострочные версии std: string и std ::wstring для удобства копирования и вставки:

      (newString._Mypair._Myval2._Myres < 16) ? strcmp(newString._Mypair._Myval2._Bx._Buf, "short") == 0 : false

(newString._Mypair._Myval2._Myres < 16) ? false : strcmp(newString._Mypair._Myval2._Bx._Ptr, "My_test_str_value_longer_than_16_chars") == 0

(newString._Mypair._Myval2._Myres < 16) ? strcmp(newString._Mypair._Myval2._Bx._Buf, "My_test_string") == 0 : strcmp(newString._Mypair._Myval2._Bx._Ptr, "My_test_string") == 0


(newString._Mypair._Myval2._Myres < 16) ? wcscmp(newString._Mypair._Myval2._Bx._Buf, L"short") == 0 : false

(newString._Mypair._Myval2._Myres < 16) ? false : wcscmp(newString._Mypair._Myval2._Bx._Ptr, L"My_test_str_value_longer_than_16_chars") == 0

(newString._Mypair._Myval2._Myres < 16) ? wcscmp(newString._Mypair._Myval2._Bx._Buf, L"My_test_string") == 0 : wcscmp(newString._Mypair._Myval2._Bx._Ptr, L"My_test_string") == 0

Все вышеперечисленные образцы копирования / вставки протестированы на MSVC версии 16.9.10 и в программе для Windows 10.

Другие вопросы по тегам