jak utworzyć warunkowy punkt przerwania za pomocą std :: string

82

Załóżmy, że mam taką funkcję:

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

jak ustawić przerwanie warunkowe, gdy newStringma określoną wartość? (bez zmiany źródła)

ustawienie warunku newString == "my value"

nie działa punkty przerwania zostały wyłączone z błędem „nie znaleziono przeciążonego operatora”

Eli
źródło
1
Nie wiem, czy taki jest zamiar, ale Twój kod jest uszkodzony. Func1 zwraca void, ale zwracasz std :: string. Funkcja Func2 nie jest wyświetlana, ale prawdopodobnie nie zwraca std :: string, ponadto używasz operatora == (równa się) zamiast = (przypisanie).
falstro
zły przykład z mojej strony, naprawiony, ale chodziło o zilustrowanie problemu z uzyskaniem warunkowych punktów przerwania ze std :: string do działania
Eli
Powiązane z GDB: stackoverflow.com/questions/10801112/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Odpowiedzi:

49

Niektóre wyszukiwania nie znalazły żadnego sposobu, aby to zrobić. Sugerowane alternatywy to umieszczenie testu w kodzie i dodanie standardowego punktu przerwania:

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

Lub zbuduj swój test na podstawie indywidualnych porównań postaci. Nawet patrzenie na poszczególne znaki w ciągu jest nieco ryzykowne; w Visual Studio 2005 musiałem zagłębić się w zmienne składowe, takie jak

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

Żadne z tych podejść nie jest zbyt zadowalające. Powinniśmy mieć lepszy dostęp do wszechobecnej funkcji Biblioteki Standardowej.

Brad Payne
źródło
+1. Właśnie pisałem podobną odpowiedź. Jedyny sposób, jaki znam, to zajrzeć do wnętrza implementacji. Zauważ, że w przypadku std :: string może to być dość skomplikowane z powodu optymalizacji krótkich ciągów.
Adrian McCarthy
Ma to problem, który myStr._Bx._Bufjest ważny tylko wtedy, gdy myStr._Mysize < _BUF_SIZE. W przeciwnym razie musisz użyćmyStr._Bx._Ptr
RunHolt
3
Ta odpowiedź nie jest już odpowiednia dla nowszego programu Visual Studio. strcmp(myStr._Mypair._Myval2._Bx._Ptr, "xyz") == 0po prostu działa
Michael Veksler
85

W programie Visual Studio 2010/2012 jest znacznie łatwiejszy sposób.

Aby osiągnąć to, czego szukasz w ANSI, użyj tego:

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

A w unicode (jeśli newString było unicode) użyj tego:

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

Jest więcej rzeczy, które możesz zrobić niż tylko porównanie, możesz przeczytać więcej na ten temat tutaj:

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
źródło
Podoba mi się ta odpowiedź, zadziałała dla mnie (z pewnymi wyjątkami, gdy pamięć nie była dostępna).
zerwany
23
Jak sugerują inne komentarze, dostęp newString._Bx._Ptrmoże nie działać dla krótkich ciągów. W moim przypadku otrzymałem komunikat „Próbowano odczytać lub zapisać chronioną pamięć”. W przypadku krótkich ciągów (16 znaków lub mniej?), newString._Bx._BufWydaje się, że zawiera znaki.
vvnurmi
1
Czy to ma działać również w VS2015? Ponieważ wydaje mi się, że to nie działa z mojej strony ...
BmyGuest
1
Nie wiem o VS, ale o gdb możesz pisać strcmp(newString.c_str(), "my_value") == 0. Może wymagać więcej wewnętrznych obliczeń, ale nie jest łatwiejsze do zapamiętania.
Jounathaen
1
@Jounathaen Niestety nie działa w VS: „To wyrażenie ma skutki uboczne i nie zostanie ocenione”.
letmaik
19

W VS2017 możesz to zrobić

strcmp(newString._Mypair._Myval2._Bx._Buf,"myvalue")==0
Adriel Santos
źródło
3
W rzeczywistości zależy to od używanego zestawu Windows SDK. Używam 10.1.15068 z Visual Studio 2015 i to działa, podczas gdy string._Bx._Buf lub string._Bx._Ptr nie.
Stuart Welch
15

W VS2017 mogłem ustawić warunek jako:

strcmp(&newString[0], "my value") == 0
Rai
źródło
1
Działa również w VS2019 i jest znacznie bardziej oczywisty i czytelny oraz łatwiejszy do zapamiętania niż wszystkie inne odpowiedzi.
Scott Hutchinson,
8

Chociaż musiałem to obejść, używając czegoś podobnego do odpowiedzi Brada (plus używając DebugBreak (), aby oderwać się od kodu), czasami edycja / ponowna kompilacja / ponowne uruchomienie fragmentu kodu jest albo zbyt czasochłonne, albo po prostu niemożliwe .

Na szczęście najwyraźniej możliwe jest dodanie do rzeczywistych elementów klasy std :: string. Wspomniano tutaj o jednym sposobie - i chociaż przywołuje on szczególnie VS2010, nadal możesz uzyskać dostęp do poszczególnych znaków ręcznie we wcześniejszych wersjach. Więc jeśli używasz 2010, możesz po prostu użyć fajnych strcmp()funkcji i tym podobnych ( więcej informacji) , ale jeśli jesteś podobny do mnie i nadal masz rok 2008 lub wcześniej, możesz wymyślić obskurną, okropną, ale funkcjonalną alternatywę ustawiając warunek punktu przerwania, na przykład:

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

do przerwania, jeśli pierwsze trzy znaki w strVar to „abc”. Oczywiście możesz kontynuować z dodatkowymi znakami. Brzydkie ... ale teraz zaoszczędziło mi to trochę czasu.

Doug Kavendek
źródło
8

VS2012:

Właśnie użyłem poniższego warunku, ponieważ newString._Bx._Ptr (jak w odpowiedzi OBWANDO) odwołałem się do nielegalnej pamięci

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

i zadziałało ...

user2989573
źródło
3

@OBWANDO (prawie) ma rozwiązanie , ale jak słusznie wskazuje wiele komentarzy, rzeczywisty bufor zależy od rozmiaru ciągu; Widzę 16 jako próg. Wstawienie sprawdzenia rozmiaru do strcmp w odpowiednim buforze działa.

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

lub

newString._Mysize >= 16 && strcmp(newString._Bx._Ptr, "ultra super long test value") == 0
anik3th
źródło
Jest to konsekwencja optymalizacji małego bufora. Przegląd wysokiego poziomu tutaj blogs.msmvps.com/gdicanio/2016/11/17/… . Więcej szczegółowych informacji tutaj akrzemi1.wordpress.com/2014/04/14/common-optimizations
Aerom Xundes
Tak, to jest właściwe rozwiązanie. Jak wspomniano, optymalizacja małych ciągów nie przydziela pamięci, jeśli długość ciągu jest mniejsza niż 16
Serge Weinstock
2

Próbowałem użyć strcmpw gdb8.1under ubuntu18.04, ale to nie działa:

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

Zgodnie z tą odpowiedzią , strcmpjest specjalnym IFUNC , można ustawić taki warunek:

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

To dość brzydkie, nie chcę tego robić po raz drugi.

Ta odpowiedź daje znacznie lepsze rozwiązanie, używa std :: string :: compare :

condition 1 camera->_name.compare("ping") == 0
dedowsdi
źródło
1

W VS2015 możesz to zrobić

newstring[0]=='x' && newString[1]=='y' && newString[2]=='z'
Richard Whitehead
źródło
1

Porównywanie ciągów działa lepiej niż porównywanie znaków

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

To działa, ale jest bardzo niewygodne w użyciu i podatne na błędy.

name._Mypair._Myval2._Bx._Buf[0] == 'f' && 
name._Mypair._Myval2._Bx._Buf[1] == '0' && 
name._Mypair._Myval2._Bx._Buf[2] == '0'
Jas
źródło
1

Możesz przekształcić go w ciąg ac, używając w ten c_str()sposób:

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

Clyde Bazile
źródło