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"

Eli
fuente
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
Relacionado con GDB: stackoverflow.com/questions/10801112/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

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.

Brad Payne
fuente
+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

OBWANDO
fuente
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
Adriel Santos
fuente
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
Rai
fuente
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.

Doug Kavendek
fuente
8

VS2012:

Acabo de usar la condición a continuación porque newString._Bx._Ptr (como en la respuesta de OBWANDO) hacía referencia a la memoria ilegal

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

Y funcionó...

usuario2989573
fuente
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
anik3th
fuente
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
dedowsdi
fuente
1

En VS2015 puedes hacer

newstring[0]=='x' && newString[1]=='y' && newString[2]=='z'
Richard Whitehead
fuente
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'
Jas
fuente
1

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

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

Clyde Bazile
fuente