So erstellen Sie einen bedingten Haltepunkt mit std :: string

82

Angenommen, ich habe diese Funktion:

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

Wie setze ich eine bedingte Unterbrechung, wenn newStringsie einen bestimmten Wert hat? (ohne die Quelle zu ändern)

eine Bedingung setzen newString == "my value"

funktionierte nicht Die Haltepunkte wurden mit dem Fehler "Überladener Operator nicht gefunden" deaktiviert.

Eli
quelle
1
Ich weiß nicht, ob dies die Absicht ist, aber Ihr Code ist kaputt. Func1 gibt void zurück, Sie geben jedoch einen std :: string zurück. Func2 wird nicht angezeigt, gibt aber wahrscheinlich keinen std :: string zurück. Außerdem verwenden Sie den Operator == (gleich) anstelle von = (Zuweisung).
Falstro
schlechtes Beispiel auf meiner Seite, behoben, aber der Punkt war, das Problem zu veranschaulichen, einen bedingten Haltepunkt mit std :: string zum Laufen zu bringen
Eli
Verwandte für GDB: stackoverflow.com/questions/10801112/…
Ciro Santilli 法轮功 冠状 病 六四 事件 16

Antworten:

49

Einige Suchanfragen haben keine Möglichkeit gefunden, dies zu tun. Vorgeschlagene Alternativen sind, den Test in Ihren Code einzufügen und einen Standard-Haltepunkt hinzuzufügen:

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

Oder um Ihren Test aus einzelnen Charaktervergleichen aufzubauen. Sogar das Betrachten einzelner Zeichen in der Zeichenfolge ist etwas heikel. In Visual Studio 2005 musste ich mich mit den Mitgliedsvariablen wie beschäftigen

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

Keiner dieser Ansätze ist sehr zufriedenstellend. Wir sollten einen besseren Zugang zu einer allgegenwärtigen Funktion der Standardbibliothek haben.

Brad Payne
quelle
+1. Ich habe gerade eine ähnliche Antwort geschrieben. Die einzige Möglichkeit, dies zu tun, besteht darin, einen Blick in die Implementierung zu werfen. Beachten Sie, dass dies für std :: string aufgrund der Optimierung für kurze Zeichenfolgen ziemlich kompliziert werden kann.
Adrian McCarthy
Dies hat das Problem, myStr._Bx._Bufdas nur gültig ist, wenn myStr._Mysize < _BUF_SIZE. Andernfalls müssen SiemyStr._Bx._Ptr
RunHolt
3
Diese Antwort ist für neuere Visual Studio nicht mehr relevant. strcmp(myStr._Mypair._Myval2._Bx._Ptr, "xyz") == 0funktioniert einfach
Michael Veksler
85

In Visual Studio 2010/2012 gibt es einen viel einfacheren Weg.

Verwenden Sie Folgendes, um das zu erreichen, wonach Sie in ANSI suchen:

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

Und in Unicode (wenn newString Unicode wäre) verwenden Sie Folgendes:

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

Es gibt mehr Dinge, die Sie tun können als nur einen Vergleich. Hier können Sie mehr darüber lesen:

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
quelle
Ich mag diese Antwort, sie hat bei mir funktioniert (mit einigen Ausnahmen, bei denen der Speicher nicht zugänglich war).
gezupft
23
Wie andere Kommentare vorgeschlagen haben, newString._Bx._Ptrfunktioniert der Zugriff bei kurzen Zeichenfolgen möglicherweise nicht. In meinem Fall wurde "Es wurde versucht, geschützten Speicher zu lesen oder zu schreiben". Für kurze Zeichenfolgen (16 Zeichen oder weniger?) newString._Bx._BufScheint die Zeichen zu halten.
vvnurmi
1
Soll das auch in VS2015 funktionieren? Weil es an meinem Ende nicht zu funktionieren scheint ...
BmyGuest
1
Ich weiß nicht über VS, aber für GDB können Sie schreiben strcmp(newString.c_str(), "my_value") == 0. Könnte intern mehr Berechnung benötigen, ist aber imho leichter zu merken.
Jounathaen
1
@Jounathaen Funktioniert in VS leider nicht: "Dieser Ausdruck hat Nebenwirkungen und wird nicht ausgewertet."
Letmaik
19

In VS2017 können Sie tun

strcmp(newString._Mypair._Myval2._Bx._Buf,"myvalue")==0
Adriel Santos
quelle
3
Dies hängt tatsächlich vom verwendeten Windows SDK ab. Ich verwende 10.1.15068 mit Visual Studio 2015 und dies funktioniert, während string._Bx._Buf oder string._Bx._Ptr dies nicht tun.
Stuart Welch
15

In VS2017 konnte ich die Bedingung wie folgt festlegen:

strcmp(&newString[0], "my value") == 0
Rai
quelle
1
Funktioniert auch in VS2019 und ist viel offensichtlicher und lesbarer und leichter zu merken als alle anderen Antworten.
Scott Hutchinson
8

Während ich dies mit etwas ähnlichem wie Brads Antwort umgehen musste (plus DebugBreak () , um direkt aus dem Code auszubrechen), ist das Bearbeiten / Neukompilieren / erneutes Ausführen von Code manchmal entweder zu zeitaufwändig oder einfach unmöglich .

Glücklicherweise ist es anscheinend möglich, in die tatsächlichen Mitglieder der std :: string-Klasse einzusteigen. Eine Möglichkeit wird hier erwähnt - und obwohl er VS2010 speziell aufruft, können Sie in früheren Versionen immer noch manuell auf einzelne Zeichen zugreifen. Wenn Sie also 2010 verwenden, können Sie einfach die netten strcmp()Funktionen und dergleichen verwenden ( weitere Informationen) . Wenn Sie jedoch wie ich sind und noch 2008 oder früher haben, können Sie eine zerlumpte, schreckliche, aber funktionale Alternative finden durch Setzen einer Haltepunktbedingung wie folgt:

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

zu brechen, wenn die ersten drei Zeichen in strVar "abc" sind. Sie können natürlich mit zusätzlichen Zeichen weitermachen. Hässlich ... aber es hat mir gerade ein wenig Zeit gespart.

Doug Kavendek
quelle
8

VS2012:

Ich habe gerade die folgende Bedingung verwendet, weil newString._Bx._Ptr (wie in OBWANDOs Antwort) auf illegalen Speicher verwiesen wurde

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

und es hat funktioniert...

user2989573
quelle
3

@OBWANDO hat (fast) die Lösung , aber wie mehrere Kommentare zu Recht zeigen, hängt der tatsächliche Puffer von der Zeichenfolgengröße ab. Ich sehe 16 als Schwelle. Das Voranstellen einer Größenprüfung für strcmp im entsprechenden Puffer funktioniert.

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

oder

newString._Mysize >= 16 && strcmp(newString._Bx._Ptr, "ultra super long test value") == 0
anik3th
quelle
Dies ist eine Folge der Optimierung des kleinen Puffers. Übersicht auf hoher Ebene hier blogs.msmvps.com/gdicanio/2016/11/17/… . Weitere Informationen
finden Sie
Ja, das ist die richtige Lösung. Wie bereits erwähnt, weist die Optimierung für kleine Zeichenfolgen keinen Speicher zu, wenn die Zeichenfolgenlänge weniger als 16 beträgt
Serge Weinstock,
2

Versucht, strcmpin gdb8.1unter zu verwenden ubuntu18.04, aber es funktioniert nicht:

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

Nach dieser Antwort , strcmpist eine spezielle IFUNC , kann man Bedingung wie folgt einrichten :

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

Es ist ziemlich hässlich, ich will es nicht das zweite Mal machen.

Diese Antwort bietet eine viel bessere Lösung, sie verwendet std :: string :: compare :

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

In VS2015 können Sie tun

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

Das Vergleichen von Zeichenfolgen funktioniert besser als das Vergleichen von Zeichen

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

Dies funktioniert, ist jedoch sehr unpraktisch und fehleranfällig.

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

Sie können es c_str()wie folgt in einen Wechselstrom-String umwandeln :

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

Clyde Bazile
quelle