how to create conditional breakpoint with std::string

Viewed 67396

Suppose I have this function:

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

how do I set a conditional break when newString has a specific value ? (without changing the source)

setting a condition newString == "my value"

didn't work the breakpoints got disabled with an error "overloaded operator not found"

12 Answers

In VS2017, I was able to set the condition as:

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

VS2012:

I just used the condition below because newString._Bx._Ptr ( as in OBWANDO's answer ) referenced illegal memory

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

and it worked...

@OBWANDO (almost) has the solution, but as multiple comments rightly point out, the actual buffer depends on the string size; I see 16 to be the threshold. Prepending a size check to the strcmp on the appropriate buffer works.

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

or

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

Tried to use strcmp in gdb8.1 under ubuntu18.04, but it doesn't work:

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

According to this answer, strcmp, is a special IFUNC, one can setup condition like this:

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

It's pretty ugly, don't want to do it the second time.

This answer gives a much better solution, it use std::string::compare :

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

Comparing string works better than comparing characters

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

This works, but is very inconvenient to use and error prone.

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

You could convert it into a c string using c_str() like so:

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

To set a conditional breakpoint in std::string you need to set it on real internal members of std::string. What you see on watch window is simplified.

You can display real structure of a variable in the watch window by using ,! suffix. In your example:

newString,!

For MSVC 2015 – 2019 you can use:

For string that were never longer than 15 characters:

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

For (even historically) longer strings:

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

Beware:

  • The variable name is written twice in each condition!
  • You need whole expression on single line. Use the copy-paste versions bellow.

Universal condition needs to put the test value twice and variable name three times:

(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

Notes: use wcscmp instead of strcmp if you are working with std::wstring.

Find more info on small string optimization in C++ https://vorbrodt.blog/2019/03/30/sso-of-stdstring/ includes sample code to find size of string's internal buffer.

All std:string and std::wstring single line versions for your copy paste convenience:

(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

All above copy/paste samples tested on MSVC version 16.9.10 and program for Windows 10.

Related