cómo crear un punto de interrupción condicional con std :: string


81

Supongamos que tengo esta función:

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

¿Cómo establezco una ruptura condicional cuando newStringtiene un valor específico? (sin cambiar la fuente)

establecer una condición newString == "my value"

no funcionó, los puntos de interrupción se desactivaron con un error "operador sobrecargado no encontrado"


1
No sé si esta es la intención, pero su código está roto. Func1 devuelve void, pero devuelve std :: string. Func2 no se muestra, pero probablemente no devuelve un std :: string, además está usando el operador == (igual) en lugar de = (asignación).
falstro

mal ejemplo de mi lado, arreglado, pero el punto era ilustrar el problema de obtener puntos de interrupción condicionales con std :: string para que funcionen
Eli

Respuestas:


49

Algunas búsquedas no han podido encontrar ninguna forma de hacer esto. Las alternativas sugeridas son poner la prueba en su código y agregar un punto de interrupción estándar:

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

O para construir su prueba a partir de comparaciones de personajes individuales. Incluso mirar caracteres individuales en la cadena es un poco arriesgado; en Visual Studio 2005 tuve que profundizar en las variables miembro como

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

Ninguno de estos enfoques es muy satisfactorio. Deberíamos tener un mejor acceso a una característica omnipresente de la Biblioteca estándar.


+1. Solo estaba escribiendo una respuesta similar. La única forma que conozco de hacer esto es echar un vistazo dentro de la implementación. Tenga en cuenta que para std :: string, esto puede complicarse bastante debido a la optimización de la cadena corta.
Adrian McCarthy

Esto tiene el problema de que myStr._Bx._Bufsolo es válido cuando myStr._Mysize < _BUF_SIZE. De lo contrario, es necesario utilizarmyStr._Bx._Ptr
RunHolt

3
Esta respuesta ya no es relevante para Visual Studio más nuevo. strcmp(myStr._Mypair._Myval2._Bx._Ptr, "xyz") == 0simplemente funciona
Michael Veksler

85

Existe una forma mucho más sencilla en Visual Studio 2010/2012.

Para lograr lo que busca en ANSI, use esto:

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

Y en unicode (si newString fuera unicode) use esto:

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

Hay más cosas que puede hacer que solo comparar, puede leer más sobre esto aquí:

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


Me gusta esta respuesta, funcionó para mí (con algunas excepciones en las que la memoria no era accesible).
arrancado el

23
Como han sugerido otros comentarios, es newString._Bx._Ptrposible que el acceso no funcione para cadenas cortas. En mi caso obtuve "Intento de leer o escribir en memoria protegida". Para cadenas cortas (¿16 caracteres o menos?), newString._Bx._BufParece contener los caracteres.
vvnurmi

1
¿Se supone que esto también funciona en VS2015? Porque no parece funcionar en mi extremo ...
BmyGuest

1
No sé sobre VS, pero para gdb puedes escribir strcmp(newString.c_str(), "my_value") == 0. Puede que necesite más cálculos internos, pero en mi humilde opinión es más fácil de recordar.
Jounathaen

1
@Jounathaen Desafortunadamente, no funciona en VS: "Esta expresión tiene efectos secundarios y no se evaluará".
letmaik

19

En VS2017 puedes hacer

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

3
De hecho, depende del SDK de Windows que esté utilizando. Estoy usando 10.1.15068 con Visual Studio 2015 y esto funciona, mientras que string._Bx._Buf o string._Bx._Ptr no lo hacen.
Stuart Welch

13

En VS2017, pude establecer la condición como:

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

También funciona en VS2019, y es mucho más obvio, legible y más fácil de recordar que todas las demás respuestas.
Scott Hutchinson

8

Si bien tuve que solucionar esto usando algo similar a la respuesta de Brad (además de usar DebugBreak () para romper directamente con el código), a veces editar / recompilar / volver a ejecutar un poco de código consume demasiado tiempo o simplemente es imposible .

Afortunadamente, aparentemente es posible escribir en los miembros reales de la clase std :: string. Aquí se menciona una forma , y aunque menciona VS2010 específicamente, aún puede acceder a caracteres individuales manualmente en versiones anteriores. Entonces, si está usando 2010, puede usar las strcmp()funciones agradables y similares ( más información) , pero si es como yo y todavía tiene 2008 o antes, puede encontrar una alternativa desigual, terrible pero funcional estableciendo un punto de interrupción condicional algo como:

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

romper si los primeros tres caracteres de strVar son "abc". Puede continuar con caracteres adicionales, por supuesto. Feo ... pero me ha ahorrado un poco de tiempo ahora.



3

@OBWANDO (casi) tiene la solución , pero como señalan acertadamente varios comentarios, el búfer real depende del tamaño de la cadena; Veo que 16 es el umbral. Funciona anteponiendo una verificación de tamaño al strcmp en el búfer apropiado.

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

o

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

Esto es una consecuencia de la optimización del búfer pequeño. Resumen de alto nivel aquí blogs.msmvps.com/gdicanio/2016/11/17/… . Más en profundidad aquí akrzemi1.wordpress.com/2014/04/14/common-optimizations
Aerom Xundes

2

Intenté usar strcmpen gdb8.1under ubuntu18.04, pero no funciona:

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

De acuerdo con esta respuesta , strcmpes un IFUNC especial , se puede configurar una condición como esta:

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

Es bastante feo, no quiero hacerlo la segunda vez.

Esta respuesta ofrece una solución mucho mejor, usa std :: string :: compare :

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


1

Comparar cadenas funciona mejor que comparar caracteres

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

Esto funciona, pero es muy incómodo de usar y propenso a errores.

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

1

Puede convertirlo en una cadena de CA usando c_str()así:

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.