Na ovoj stranici

Pomoćnici za otklanjanje pogrešaka

Qt Creator koristi Python skripte za prevođenje sirovog sadržaja memorije i podataka o informacijama o tipu iz pozadinskih sustava za otklanjanje pogrešaka (trenutno podržani GDB, LLDB i CDB) u oblik prikazan korisniku u prikazima Locals i Expressions.

Za razliku od GDB-ovih pretty printera i LLDB-ovih formata podataka, Qt Creator-ovi pomoćnici za otklanjanje pogrešaka ne ovise o izvornom backendu za otklanjanje pogrešaka. To znači da se isti kod može koristiti s GDB-om na Linuxu, LLDB-om na macOS-u i CDB-om na Windowsima, ili na bilo kojoj drugoj platformi na kojoj je dostupna barem jedna od tri podržana backenda.

Da biste koristili zadane GDB-ove uređivače izgleda instalirane na vašem sustavu ili povezane s bibliotekama koje vaša aplikacija koristi, idite na Preferences > Debugger > GDB > Load system GDB pretty printers. Za više informacija pogledajte GDB.

GDB kartica u postavkama otklanjanja pogrešaka

Prilagodba ugrađenih pomoćnika za otklanjanje pogrešaka

Možete izvršiti naredbe nakon što su ugrađeni pomoćnici za otklanjanje pogrešaka učitani i potpuno inicijalizirani. Za učitavanje dodatnih pomoćnika za otklanjanje pogrešaka ili izmjenu postojećih, idite na Preferences > Debugger > Locals & Expressions i unesite naredbe u polje Debugging Helper Customization.

kartica Lokalne varijable i izrazi u postavkama otklanjanja pogrešaka

Ako primate poruke o pogreškama o primanju signala pri korištenju GDB-a, možete navesti GDB naredbe za rukovanje signalima. Na primjer, možete reći GDB-u da zanemari signal SIGSTOP ako primite sljedeću poruku o pogrešci: The debugged process stopped because it received a signal from the operating system. Signal name: SIGSTOP.

Da biste zaustavili GDB u obradi signala SIGSTOP, dodajte sljedeće naredbe u polje Debugging Helper Customization:

handle SIGSTOP nopass
handle SIGSTOP nostop

Da biste prikazali okvir za poruke čim vaša aplikacija primi signal tijekom otklanjanja pogrešaka, idite na Preferences > Debugger > GDB > Show a message box when receiving a signal.

Dodavanje prilagođenih pomoćnika za otklanjanje pogrešaka

Za dodavanje debug pomoćnika za vlastite tipove nije potrebna kompilacija, dovoljno je dodati nekoliko redaka Pythona. Skripte mogu istovremeno obrađivati više verzija Qt-a ili vlastite biblioteke.

Da biste dodali pomoćnike za otklanjanje pogrešaka za prilagođene tipove, dodajte implementacije pomoćnika za otklanjanje pogrešaka u početnu datoteku otklanjača (na primjer, ~/.gdbinit ili ~/.lldbinit) ili ih navedite izravno u Additional Startup Commands u Preferences > Debugger > GDB.

Za početak implementacije pomoćnika za otklanjanje pogrešaka za vlastite tipove podataka, njihovu implementaciju možete smjestiti u datoteku share/qtcreator/debugger/personaltypes.py u vašoj Qt instalaciji ili u samostalnoj instalaciji Qt Creator. Na macOS-u je datoteka uključena u paket aplikacije Qt Creator, gdje se nalazi u mapi Contents/resources/debugger.

Datoteka personaltypes.py sadrži jedan primjer implementacije:

# def qdump__MapNode(d, value):
#    d.putValue("This is the value column contents")
#    d.putExpandable()
#    if d.isExpanded():
#        with Children(d):
#            # Compact simple case.
#            d.putSubItem("key", value["key"])
#            # Same effect, with more customization possibilities.
#            with SubItem(d, "data")
#                d.putItem("data", value["data"])

Za dodavanje pomoćnih alata za otklanjanje pogrešaka:

  1. Otvorite datoteku share/qtcreator/debugger/personaltypes.py za uređivanje. Na primjer, ako se vaša Qt instalacija nalazi u direktoriju Qt5 na Windowsu, pogledajte u C:\Qt5\Tools\QtCreator\share\qtcreator\debugger. Na macOS-u pogledajte u Qt5/Qt Creator.app/Contents/resources/debugger.
  2. Dodajte svoju implementaciju dumpéra na kraj datoteke personaltypes.py. Za više informacija o implementaciji pomoćnika za otklanjanje pogrešaka pogledajte sljedeće odjeljke.
  3. Kako biste spriječili prebrisavanje datoteke personaltypes.py prilikom ažuriranja instalacije Qt Creator (na primjer, prilikom ažuriranja instalacije Qt-a), kopirajte je na sigurno mjesto izvan instalacije Qt Creator na vašem sustavu datoteka i navedite tu lokaciju u Preferences > Debugger > Locals & Expressions > Extra Debugging Helper.

Prilagođeni pomoćnici za otklanjanje pogrešaka automatski će se preuzeti s personaltypes.py kada pokrenete sesiju otklanjanja pogrešaka u Qt Creator ili odaberete Reload Debugging Helpers iz kontekstnog izbornika prikaza dnevnika otklanjanja pogrešaka.

Pregled pomoćnika za otklanjanje pogrešaka

Implementacija pomoćnika za otklanjanje pogrešaka obično se sastoji od jedne Python funkcije koja mora biti nazvana qdump__NS__Foo, pri čemu je NS::Foo klasa ili predložak klase koji se ispituje. Primijetite da se operator za rješavanje imenskog prostora :: zamjenjuje dvostrukim podcrtima: __. Mogući su i ugniježđeni imenski prostori. Argumenti predloška se ne koriste za izgradnju naziva funkcije.

Primjeri:

  • Naziv funkcije koja implementira pomoćnik za otklanjanje pogrešaka za tip namespace Project { template<typename T> struct Foo {... } } je qdump__Project__Foo.
  • Naziv funkcije koja implementira pomoćnik za otklanjanje pogrešaka za tip std::__1::vector<T>::iterator je qdump__std____1__vector__iterator.

Qt Creator's debugger dodatak poziva ovu funkciju kad god želite prikazati objekt ove vrste. Funkciji se prosljeđuju sljedeći parametri:

  • d od tipa Dumper, objekt koji ima trenutne postavke i pruža mogućnosti za izgradnju objekta koji predstavlja dio prikaza Locals i Expressions.
  • value tipa Value, koji obavija ili gdb.Value ili lldb.SBValue.

Funkcija qdump__* mora napojiti objekt Dumper određenim informacijama koje se koriste za izgradnju prikaza objekta i njegovih podređenih elemenata u prikazima Locals i Expressions.

Primjer:

def qdump__QFiniteStack(d, value):
    alloc = value["_alloc"].integer()
    size = value["_size"].integer()
    d.putItemCount(size)
    if d.isExpanded():
        d.putArrayData(value["_array"], size, value.type[0])

Napomena: Da biste stvorili dumper funkcije koje se mogu koristiti s obje LLDB i GDB pozadinske instance, izbjegavajte izravan pristup imenskim prostorima gdb.* i lldb.* te umjesto toga koristite metode klase Dumper.

Da biste došli do osnovne instance objekta u pomoćniku za otklanjanje pogrešaka, upotrijebite funkciju value.base() ili sljedeći primjer koda:

def qdump__A(d, value):
   t = value.members(True)[0].type
   dptr, base_v = value.split('p{%s}' % t.name)
   d.putItem(base_v)

Pomoćnici za otklanjanje pogrešaka mogu se postaviti da se pozivaju kad god naziv tipa odgovara regularnom izrazu. Da biste to učinili, naziv funkcije pomoćnika za otklanjanje pogrešaka mora započeti s qdump__ (s dva znaka podcrtavanja). Osim toga, funkcija mora imati treći parametar nazvan regex s zadanoj vrijednošću koja određuje regularni izraz kojem naziv tipa treba odgovarati.

Na primjer, kompajler Nim 0.12 dodjeljuje umjetna imena, kao što su TY1 i TY2, svim generičkim sekvencama koje kompajlira. Za njihovu vizualizaciju u Qt Creator može se koristiti sljedeći pomoćnik za otklanjanje pogrešaka:

def qdump__NimGenericSequence__(d, value, regex = "^TY.*$"):
    size = value["Sup"]["len"]
    base = value["data"].dereference()
    typeobj = base.dereference().type
    d.putArrayData(base, size, typeobj)

Implementacija pomoćnika za otklanjanje pogrešaka

Pomoćnik za otklanjanje pogrešaka stvara opis prikazanog stavka podataka u formatu sličnom GDB/MI i JSON-u.

Za svaki redak u prikazima Locals i Expressions potrebno je stvoriti niz poput sljedećeg i proslijediti ga dodatku za otklanjanje pogrešaka.

{ iname='some internal name',           # optional
  address='object address in memory',   # optional
  name='contents of the name column',   # optional
  value='contents of the value column',
  type='contents of the type column',
  numchild='number of children',        # zero/nonzero is sufficient
  children=[              # only needed if item is expanded in view
     {iname='internal name of first child',
       },
     {iname='internal name of second child',
       },

  ]}

Vrijednost polja iname je interno ime objekta, koje se sastoji od popisa identifikatora odvojenih točkom, a odgovara položaju prikaza objekta u pogledu. Ako nije prisutno, generira se spajanjem iname-a roditeljskog objekta, točke i slijednog broja.

Vrijednost polja name prikazuje se u stupcu Name pogleda. Ako nije navedena, umjesto toga se koristi jednostavan broj u zagradama.

Budući da stabilnost formata nije zajamčena, snažno se preporučuje da ne generirate format za prijenos izravno, već da koristite sloj apstrakcije klasa Python Dumper, točnije samu klasu Dumper i apstrakcije Dumper:Value i Dumper:Type. One nude potpuni okvir za rukovanje poljima iname i addr, za obradu djece jednostavnih tipova, referenci, pokazivača, enuma te poznatih i nepoznatih struktura, kao i neke praktične funkcije za rješavanje uobičajenih situacija.

Kada koristite CDB kao pozadinski debuger, možete omogućiti Python dumper odabirom Preferences > Debugger > CDB > Use Python dumper.

CDB kartica u postavkama otklanjanja pogrešaka

Sljedeći odjeljci opisuju neke od široko korištenih klasa i članova Dumpera navedenih u qtcreator\share\qtcreator\debugger\dumper.py.

Klasa Dumper

Klasa Dumper ima generičke, nisko-razinske i praktične funkcije:

  • putItem(self, value) - Glavna funkcija koja izravno obrađuje osnovne tipove, reference, pokazivače i enume, prolazi kroz temeljne klase i članove složenih tipova te po potrebi poziva funkcije qdump__*.
  • putIntItem(self, name, value) - Ekvivalentno:
    with SubItem(self, name):
        self.putValue(value)
        self.putType("int")
  • putBoolItem(self, name, value) - Ekvivalentno:
    with SubItem(self, name):
        self.putValue(value)
        self.putType("bool")
  • putCallItem(self, name, rettype, value, func, *args) - Koristi backend otklonitelja pogrešaka (debugger) za postavljanje poziva funkcije func koja vraća rettype na vrijednost navedenu u value i za ispis dobivenog stavka.

    Nativni pozivi su izuzetno moćni i, na primjer, mogu iskoristiti postojeće alate za otklanjanje pogrešaka ili logiranje u procesu koji se otklanja. Međutim, trebali bi se koristiti samo u kontroliranom okruženju i samo ako ne postoji drugi način pristupa podacima, iz sljedećih razloga:

    • Izravno izvođenje koda je opasno. Izvršava nativni kod s privilegijima procesa podvrgnutog otklanjanju pogrešaka, što može dovesti ne samo do oštećenja tog procesa, već i do pristupa disku i mreži.
    • Pozivi se ne mogu izvršiti pri pregledavanju core datoteke.
    • Pozivi su skupi za postavljanje i izvršavanje u otklanjivaču pogrešaka.
  • putArrayData(self, address, itemCount, type) - Stvara broj podređenih procesa navedenih pomoću itemCount, tipa type, iz objekta nalik nizu smještenog na address.
  • putSubItem(self, component, value) - Ekvivalentno:
    with SubItem(self, component):
        self.putItem(value)

    Izuzeci podignuti u pozivima funkcija unutar funkcija se uhvate i sav izlaz proizveden od strane putItem zamjenjuje se izlazom od:

    except RuntimeError:
        d.put('value="<invalid>",type="<unknown>",numchild="0",')
    -ph-0000@deepl.internal tipa xml-ph-0001@deepl.internal objekta nalik nizu smještenog na xml-ph-0002
  • put(self, value) - Funkcija niske razine za izravno dodavanje u izlaznu niz. To je također najbrži način dodavanja izlaza.
  • putField(self, name, value) - Dodaje polje name='value'.
  • childRange(self) - Vraća raspon djece specificiran u trenutnom opsegu Children.
  • putItemCount(self, count) - Dodaje polje value='<%d items>' u izlaz.
  • putName(self, name) - Dodaje polje name=''.
  • putType(self, type, priority=0) - Dodaje polje type='', osim ako se type ne podudara s zadanim tipom djeteta roditelja ili je putType već pozvan za trenutni element s višom vrijednošću priority.
  • putBetterType(self, type) - Prepisuje posljednje zabilježeno type.
  • putExpandable(self) - Obavještava o postojanju podređenih stavki za trenutnu vrijednost. Po zadanom nema podređenih stavki.
  • putNumChild(self, numchild) - Objavljuje postojanje (numchild > 0) ili nepostojanje podređenih stavki za trenutnu vrijednost.
  • putValue(self, value, encoding = None) - Dodaje datoteku value='', opcionalno praćenu poljem valueencoding=''. value mora biti pretvoriv u niz koji se u potpunosti sastoji od alfanumeričkih vrijednosti. Parametar encoding može se koristiti za navođenje kodiranja u slučaju da je stvarna vrijednost morala biti nekako kodirana kako bi zadovoljila uvjet da sadrži samo alfanumeričke znakove. Parametar encoding je niz oblika codec:itemsize:quote, gdje je codec bilo koji od sljedećih: latin1, utf8, utf16, ucs4, int ili float. itemsize određuje veličinu osnovne komponente objekta ako to nije implicitno definirano parametrom codec, a quote određuje treba li vrijednost biti okružena navodnicima pri prikazu.

    Primjer:

    # Safe transport of quirky data. Put quotes around the result.
    d.putValue(d.hexencode("ABC\"DEF"), "utf8:1:1")
  • putStringValue(self, value) - Kodira QString i poziva putValue s ispravnom postavkom encoding.
  • putByteArrayValue(self, value) - Kodira QByteArray i poziva putValue s ispravnom postavkom encoding.
  • isExpanded(self) - Provjerava je li trenutni element proširen u prikazu.
  • createType(self, pattern, size = None) - Stvara objekt Dumper.Type. Točna operacija ovisi o pattern.
    • Ako pattern odgovara nazivu dobro poznate vrste, vraća se objekt Dumper.Type koji opisuje tu vrstu.
    • Ako je pattern ime tipa poznatog nativnom backendu, vraćeni tip opisuje nativni tip.
    • U suprotnom se pattern koristi za izgradnju opisa tipa interpretiranjem niza stavki koje opisuju polje strukture na sljedeći način. Opisi polja sastoje se od jednog ili više znakova na sljedeći način:
      • q - Potpisani 8-bajtni cjelobrojni broj
      • Q - Nesignirana 8-bajta cijela vrijednost
      • i - Potpisana 4-bajtna cjelobrojna vrijednost
      • I - Nesignirana 4-bajta cijela vrijednost
      • h - Potpisana 2-bajtna cjelobrojna vrijednost
      • H - Neznakovani 2-bajtni cjelobrojni broj
      • b - Potpisana 1-bajtna cjelobrojna vrijednost
      • B - Bezpredznakova 1-bajtna cjelobrojna vrijednost
      • d - 8-bajtna IEEE 754 vrijednost s pomičnom zarezom
      • f - 4-bajtna IEEE 754 vrijednost s pomičnom zarezom
      • p - Pokazatelj, tj. bezpredznakova cjelobrojna vrijednost odgovarajuće veličine prema ciljnoj arhitekturi
      • @ - Primjereno popunjavanje. Veličina se određuje prethodnim i sljedećim poljem te ciljnom arhitekturom
      • <n>s - Blob od <n> bajtova, s implicitnim poravnanjem od 1
      • <typename> - Blob odgovarajuće veličine i odgovarajućeg poravnanja određen pomoću Dumper.Type a s imenom typename
    - Pokazivač, tj. bezpredznakova cjelobrojna vrijednost odgovarajuće veličine prema ciljnoj arhitektu

Klasa Dumper.Type

Klasa Dumper.Type opisuje tip dijela podataka, obično C++ klasu ili strukturu, pokazatelj na strukturu ili primitivni tip, kao što je cjelobrojni ili pomični tip.

Objekti tipa, odnosno instancije klase Dumper.Type, mogu se stvoriti pomoću back-endova otklonitelja pogrešaka, obično evaluacijom informacija za otklanjanje pogrešaka ugrađenih u binarnu datoteku ili priloženih uz nju, ili se mogu stvoriti u hodu pomoću pomoćnika za otklanjanje pogrešaka.

Qt Creator nudi informacije o tipu u hodu za većinu Qt klasa, čime se ukida potreba za korištenjem debug verzija Qt-a u svrhu introspekcije objekata.

Klasa Dumper.Type ima sljedeće široko korištene članice:

  • name - Naziv ove vrste kao niz znakova, ili None ako je vrsta anonimna.
  • size(self) - Vraća veličinu objekta ove vrste u bajtima.
  • bitsize(self) - Vraća veličinu objekta ove vrste u bitovima.
  • alignment(self) - Vraća potrebnu poravnatost za objekte ove vrste u bajtima.
  • deference(self) - Vraća tip dereferenciranja za pokazivački tip, inače None.
  • pointer(self) - Vraća tip pokazivača koji se može dereferencirati na ovaj tip.
  • target(self) - Pomoćna funkcija koja vraća tip stavke za tipove nizova i tip nakon dereferenciranja za pokazivače i reference.
  • stripTypedefs(self) - Vraća temeljni tip ako je ovaj tip alias.
  • templateArgument(self, position, numeric = False) - Vraća parametar predloška na adresi position ako je ovo tip s predloškom. Ako je numeric True , vraća parametar kao cjelobrojnu vrijednost.
  • fields(self) - Vraća popis Dumper:Fields koji opisuju temeljne klase i članove podataka ove vrste.

Klasa Dumper.Field

Klasa Dumper.Field opisuje osnovnu klasu ili član podataka objekta:

  • isBaseClass - Razlikuje temeljne klase i članove podataka.
  • fieldType(self) - Vraća tip ove osnovne klase ili člana podataka.
  • parentType(self) - Vraća vlasnički tip.
  • bitsize(self) - Vraća veličinu ovog polja u bitima.
  • bitpos(self) - Vraća pomak ovog polja u vlasničkom tipu u bitima.

Klasa Dumper.Value

Klasa Dumper.Value opisuje dio podataka, kao što su instance C++ klasa ili primitivni tipovi podataka. Također se može koristiti za opisivanje umjetnih stavki koje nemaju izravnu reprezentaciju u memoriji, kao što su sadržaj datoteka, neuzastopni objekti ili kolekcije.

Dumper.Value uvijek ima pridruženu Dumper.Type. Dvije glavne reprezentacije stvarnih podataka vrijednosti su:

  • Python objekt koji slijedi Python protokol za buffer, kao što je Python memoryview ili bytes objekt. size() mora odgovarati veličini tipa ove vrijednosti.
  • Integer vrijednost koja predstavlja pokazivač na početak objekta u trenutnom adresnom prostoru. Veličinu objekta određuje size() njegovog tipa.

Dumper.Value Poznavanje interne reprezentacije objekta obično nije potrebno pri izradi pomoćnika za otklanjanje pogrešaka za njega.

Član funkcija i svojstva klase Dumper.Value su sljedeći:

  • integer(self) - Vraća interpretaciju ove vrijednosti kao potpisani integralni broj odgovarajuće veličine.
  • pointer(self) - Vraća interpretaciju ove vrijednosti kao pokazivač u trenutnom adresnom prostoru.
  • members(self, includeBases) - Vraća popis objekata klase Dumper.Value koji predstavljaju osnovne objekte i članove podataka ove vrijednosti.
  • dereference(self) - Za vrijednosti koje opisuju pokazivače vraća dereferenciranu vrijednost, a inače vraća None.
  • cast(self, type) - Vraća vrijednost koja ima iste podatke kao i ova vrijednost, ali tipa type.
  • address(self) - Vraća adresu ove vrijednosti ako se sastoji od uzastopnog područja u trenutnom adresnom prostoru, a inače vraća None.
  • data(self) - Vraća podatke ove vrijednosti kao Python objekt bytes.
  • split(self, pattern) - Vraća popis vrijednosti stvorenih prema pattern iz podataka ove vrijednosti. Prihvatljivi obrasci su isti kao i za Dumper.createType.
  • dynamicTypeName(self) - Pokušava dohvatiti naziv dinamičkog tipa ove vrijednosti ako je riječ o objektu temeljne klase. Vraća None ako to nije moguće.

Klasa Children i SubItem

Pokušaj stvaranja podređenih stavki može dovesti do pogrešaka ako su podaci neinizicirani ili oštećeni. Za uredno oporavak u takvim situacijama koristite upravljače konteksta Children i SubItem za stvaranje ugniježđenih stavki.

__init__(self, dumper, numChild = 1, childType = None, childNumChild = None, maxNumChild = None, addrBase = None, addrStep = None) Konstruktor klase Children koristi jedan obavezni i nekoliko neobaveznih argumenata. Obavezni argument odnosi se na trenutni objekt Dumper. Neobavezni argumenti mogu se koristiti za navođenje broja djece numChild, pri čemu se za unuke navodi tip childType_ i childNumChild_. Ako je naveden maxNumChild, prikazat će se samo toliko djece. Ovo se treba koristiti pri ispisivanju sadržaja spremnika koji bi inače mogli potrajati predugo. Parametri addrBase i addrStep mogu se koristiti za smanjenje količine podataka koje proizvode dječji dumpers. Ispis adrese za n-tidječji element bit će suzdržan ako je njegova adresa jednaka addrBase + n * addrStep.

Primjer:

if d.isExpanded():
    with Children(d):
        with SubItem(d):
            d.putName("key")
            d.putItem(key)
        with SubItem(d):
            d.putName("value")
            d.putItem(value)

Imajte na umu da se ovo može praktičnije napisati kao:

d.putNumChild(2)
if d.isExpanded():
    with Children(d):
        d.putSubItem("key", key)
        d.putSubItem("value", value)

Vidi također Kako: Debugiranje, Debugiranje, Debugeri i Debugger.

Copyright © The Qt Company Ltd. and other contributors. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.