【问题标题】:how to create conditional breakpoint with std::string如何使用 std::string 创建条件断点
【发布时间】:2010-12-16 23:39:44
【问题描述】:

假设我有这个功能:

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

newString 具有特定值时,如何设置条件中断? (不改变来源)

设置条件newString == "my value"

没有工作,断点因错误“未找到重载运算符”而被禁用

【问题讨论】:

  • 我不知道这是否是意图,但您的代码已损坏。 Func1 返回 void,但您返回 std::string。 Func2 未显示,但它可能不会返回 std::string,此外,您使用的是 ==(等于)运算符而不是 =(赋值)。
  • 我这边的坏例子,已修复,但重点是说明使用 std::string 获得条件断点的问题
  • 在页面下方查看其他版本的 Visual Studio 的答案。感谢@Rai 对于 VS 2017+。要记住的实际简单实现。

标签: visual-studio debugging conditional-breakpoint


【解决方案1】:

一些搜索未能找到任何方法来做到这一点。建议的替代方法是将测试放入您的代码并添加标准断点:

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

或者通过个人字符比较来建立您的测试。即使查看字符串中的单个字符也有点冒险。在 Visual Studio 2005 中,我不得不深入研究成员变量,例如

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

这些方法都不是很令人满意。我们应该可以更好地使用标准库的普遍功能。

【讨论】:

  • +1。我只是在写一个类似的答案。我知道的唯一方法是查看实现。请注意,对于 std::string,由于短字符串优化,这可能会变得非常复杂。
  • 这里有myStr._Bx._Buf只在myStr._Mysize < _BUF_SIZE时有效的问题。否则你需要使用myStr._Bx._Ptr
  • 此答案与较新的 Visual Studio 不再相关。 strcmp(myStr._Mypair._Myval2._Bx._Ptr, "xyz") == 0 有效
【解决方案2】:

虽然我不得不使用类似于 Brad 的答案(加上使用 DebugBreak() 直接从代码中中断)来解决这个问题,但有时编辑/重新编译/重新运行一些代码要么太耗时,要么简直是不可能的。

幸运的是,显然可以深入研究 std::string 类的实际成员。提到了一种方法here——尽管他特别提到了 VS2010,但您仍然可以在早期版本中手动访问单个字符。因此,如果您使用的是 2010,您可以只使用漂亮的 strcmp() 函数等(more info),但如果您像我一样仍然拥有 2008 或更早版本,您可以想出一个破烂的,可怕的,但是通过设置断点条件来替代功能,例如:

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

如果 strVar 中的前三个字符是“abc”,则中断。当然,您可以继续使用其他字符。丑陋的..但它刚刚为我节省了一点时间。

【讨论】:

    【解决方案3】:

    在 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

    【讨论】:

    • 正如其他 cmets 所建议的,访问 newString._Bx._Ptr 可能不适用于短字符串。就我而言,我得到“尝试读取或写入受保护的内存”。对于短字符串(16 个字符或更少?),newString._Bx._Buf 似乎包含字符。
    • 这应该也适用于 VS2015 吗?因为它似乎对我不起作用......
    • 我不知道VS,但是对于gdb你可以写strcmp(newString.c_str(), "my_value") == 0。内部可能需要更多计算,但更容易记住。
    • @Jounathaen 不幸的是在 VS 中不起作用:“这个表达式有副作用,不会被计算。”
    • newString.c_str() 在 MSVC 2019 中不起作用(在版本 16.9.10 中测试),因为它抱怨:“这个表达式有副作用,不会被评估。”。 (尽管 c_str() 函数是 const,它还是会抱怨。)
    【解决方案4】:

    VS2012:

    我只是使用了下面的条件,因为newString._Bx._Ptr( as in OBWANDO's answer )引用了非法内存

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

    它成功了……

    【讨论】:

      【解决方案5】:

      在 VS2015 中你可以这样做

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

      【讨论】:

        【解决方案6】:

        在 VS2017 中你可以这样做

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

        【讨论】:

        • 这实际上取决于您使用的 Windows SDK。我将 10.1.15068 与 Visual Studio 2015 一起使用,这可以工作,而 string._Bx._Buf 或 string._Bx._Ptr 则不行。
        • strstr(processName._Mypair._Myval2._Bx._Ptr,"scr")!=0 为我工作。我试图找到一个名称中包含 scr 的进程(屏幕保护程序具有 .scr 扩展名)。
        【解决方案7】:

        @OBWANDO (almost) has the solution,但正如多个 cmets 正确指出的那样,实际缓冲区取决于字符串大小;我认为 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
        

        【讨论】:

        【解决方案8】:

        比较字符串比比较字符效果更好

        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'
        

        【讨论】:

          【解决方案9】:

          在 VS2017 中,我可以将条件设​​置为:

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

          【讨论】:

          • 也可以在 VS2019 中使用,并且比所有其他答案更明显、更易读、更容易记住。
          【解决方案10】:

          您可以使用c_str() 将其转换为 c 字符串,如下所示:

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

          【讨论】:

            【解决方案11】:

            尝试在gdb8.1ubuntu18.04下使用strcmp,但不起作用:

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

            根据这个answerstrcmp,是一个特殊的IFUNC,可以这样设置条件:

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

            太丑了,不想再做第二次了。

            这个answer 提供了一个更好的解决方案,它使用std::string::compare

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

            【讨论】:

              【解决方案12】:

              要在 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
              

              注意:如果您使用的是std::wstring,请使用wcscmp 而不是strcmp

              查找更多关于 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 的程序上测试。

              【讨论】:

                猜你喜欢
                • 2010-11-05
                • 1970-01-01
                • 2019-11-16
                • 2012-06-03
                • 2020-04-12
                • 1970-01-01
                • 2020-05-03
                • 2020-05-01
                • 2022-12-01
                相关资源
                最近更新 更多