How to create conditional breakpoint with std::string
Asked Answered
S

12

108

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 the condition newString == "my value" didn't work. The breakpoints were disabled with an error overloaded operator not found.

Skirting answered 16/11, 2009 at 8:38 Comment(5)
I don't know if this is the intention, but your code is broken. Func1 returns void, yet you return a std::string. Func2 is not shown, but it probably doesn't return a std::string, furthermore you're using the == (equals) operator rather than = (assignment).Muzhik
bad example on my side, fixed but the point was to illustrate the problem of getting a conditional breakpoints with std::string to workSkirting
Related for GDB: #10801612Prehensile
Check answers down the page for other versions of Visual Studio. Kudos to @Rai for VS 2017+. An actual simple implementation to remember.Lithuanian
Is anyone know how to compare int values?Witwatersrand
E
52

Some searching has failed to turn up any way to do this. Suggested alternatives are to put the test in your code and add a standard breakpoint:

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

Or to build up your test from individual character comparisons. Even looking at individual characters in the string is a bit dicey; in Visual Studio 2005 I had to dig down into the member variables like

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

Neither of these approaches is very satisfactory. We should have better access to a ubiquitous feature of the Standard Library.

Etienne answered 8/12, 2009 at 0:4 Comment(3)
+1. I was just writing a similar answer. The only way I know of to do this is to peek inside the implementation. Note that for std::string, this can get pretty complicated because of the short string optimization.Surprint
This has the problem that myStr._Bx._Buf is only valid when myStr._Mysize < _BUF_SIZE. Otherwise you need to use myStr._Bx._PtrOptics
This answer is no longer relevant for newer Visual Studio. strcmp(myStr._Mypair._Myval2._Bx._Ptr, "xyz") == 0 just worksHawkweed
G
98

There is a much easier way in Visual Studio 2010/2012.

To accomplish what you are looking for in ANSI use this:

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

And in unicode (if newString were unicode) use this:

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

There are more things you can do than just a compare, you can read more about it here:

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

Glazunov answered 4/3, 2013 at 7:49 Comment(8)
I like this answer, it worked for me (with some exceptions where the memory was not accessable).Garibald
As other comments have suggested, accessing newString._Bx._Ptr may not work for short strings. In my case I got "Attempted to read or write protected memory". For short strings (16 characters or less?), newString._Bx._Buf seems to hold the characters.Python
Is this supposed to work in VS2015 as well? Because it doesn't seem to work on my end...Cheryl
I don't know about VS, but for gdb you can write strcmp(newString.c_str(), "my_value") == 0. Might need more calculation internaly, but is imho easier to remember.Ladylove
@Ladylove Doesn't work in VS unfortunately: "This expression has side effects and will not be evaluated."Effy
Try your_string._Mypair._Myval2._Bx._Buf . Works in VS2015.Aldwon
if one does strcmp(m_object->m_str, "helloworld") == 0 and m_object or m_str is null this is inconvenient. any workarounds for this? noticed that m_object && m_object->m_str && strcmp(...) does not workBrutal
newString.c_str() does not work in MSVC 2019 (Tested in version 16.9.10) as it complains: "This expression has side effects and will not be evaluated.". (It complains despite c_str() function is const.)Elburr
S
65

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

strcmp(&newString[0], "my value") == 0
Sines answered 5/6, 2019 at 11:16 Comment(4)
Works in VS2019 too, and is much more obvious and readable and easier to remember than all the other answers.Acetometer
The accepted answer doesn't work for me in VS2019 (it complains about _Bx), but this does.Parsonage
VS2022 also doesn't like ._Bx at least with basic stringsMuricate
This is nice and simple without painful syntax and just works regardless of short strings or long strings. This should be the accepted answer now.Rebate
E
52

Some searching has failed to turn up any way to do this. Suggested alternatives are to put the test in your code and add a standard breakpoint:

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

Or to build up your test from individual character comparisons. Even looking at individual characters in the string is a bit dicey; in Visual Studio 2005 I had to dig down into the member variables like

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

Neither of these approaches is very satisfactory. We should have better access to a ubiquitous feature of the Standard Library.

Etienne answered 8/12, 2009 at 0:4 Comment(3)
+1. I was just writing a similar answer. The only way I know of to do this is to peek inside the implementation. Note that for std::string, this can get pretty complicated because of the short string optimization.Surprint
This has the problem that myStr._Bx._Buf is only valid when myStr._Mysize < _BUF_SIZE. Otherwise you need to use myStr._Bx._PtrOptics
This answer is no longer relevant for newer Visual Studio. strcmp(myStr._Mypair._Myval2._Bx._Ptr, "xyz") == 0 just worksHawkweed
C
23

In VS2017 you can do

strcmp(newString._Mypair._Myval2._Bx._Buf,"myvalue")==0
Campanile answered 31/7, 2017 at 22:5 Comment(2)
It actually depends on the Windows SDK you are using. I am using 10.1.15068 with Visual Studio 2015 and this works, whereas string._Bx._Buf or string._Bx._Ptr do not.Evince
strstr(processName._Mypair._Myval2._Bx._Ptr,"scr")!=0 worked for me. I was trying to find a process which has scr in its name (screen savers have .scr extention).Cartierbresson
C
8

While I've had to work around this using something similar to Brad's answer (plus using DebugBreak() to break right from the code), sometimes editing/recompiling/re-running a bit of code is either too time consuming or just plain impossible.

Luckily, it's apparently possible to spelunk into the actual members of the std::string class. One way is mentioned here -- and though he calls out VS2010 specifically, you can still access individual chars manually in earlier versions. So if you're using 2010, you can just use the nice strcmp() functions and the like (more info), but if you're like me and still have 2008 or earlier, you can come up with a raggedy, terrible, but functional alternative by setting a breakpoint conditional something like:

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

to break if the first three characters in strVar are "abc". You can keep going with additional chars, of course. Ugly.. but it's saved me a little time just now.

Calciferol answered 22/4, 2011 at 16:18 Comment(0)
S
8

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...

Slacken answered 13/11, 2013 at 21:12 Comment(0)
H
3

@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
Helga answered 11/7, 2018 at 9:29 Comment(2)
This is a consequence of the small buffer optimization. High level overview here blogs.msmvps.com/gdicanio/2016/11/17/…. More in depth here akrzemi1.wordpress.com/2014/04/14/common-optimizationsRevegetate
Yes that's the correct solution. As noted, the small string optimization does not allocate memory if the string length is less than 16Esquivel
N
2

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
Narra answered 10/1, 2020 at 6:0 Comment(0)
K
1

In VS2015 you can do

newstring[0]=='x' && newString[1]=='y' && newString[2]=='z'
Kroeger answered 5/5, 2017 at 11:17 Comment(0)
P
1

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'
Pearman answered 16/7, 2018 at 19:23 Comment(0)
C
1

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

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

Crow answered 4/10, 2019 at 16:28 Comment(0)
E
0

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.

Elburr answered 1/10, 2021 at 16:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.