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 backenda 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 formatera podataka, pomoćna sredstva za otklanjanje pogrešaka u Qt Creator u 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žane pozadinske usluge.

Da biste koristili zadane GDB-ove pretty printere 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. Da biste učitali dodatne pomoćnike za otklanjanje pogrešaka ili izmijenili postojeće, idite na Preferences > Debugger > Locals & Expressions i unesite naredbe u polje Debugging Helper Customization.

Zabavne fraze i izrazi u kartici Debugera

Ako primate poruke o pogreškama zbog primanja signala pri korištenju GDB-a, možete odrediti GDB naredbe za rukovanje tim 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 pomoćnika za otklanjanje pogrešaka za vlastite tipove nije potrebna kompilacija, dovoljno je dodati nekoliko redaka Pythona. Skripte mogu istovremeno obrađivati više verzija Qt-a ili vaše 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 ta 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, na Windowsima pogledajte u C:\Qt\Tools\QtCreator\share\qtcreator\debugger. Na macOS-u pogledajte u 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 datotečnom sustavu i navedite tu lokaciju u Preferences > Debugger > Locals & Expressions > Extra Debugging Helper.

Prilagođeni pomoćnici za otklanjanje pogrešaka automatski će se učitati iz 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. Imajte na umu da se operator za rješavanje imenskog prostora :: zamjenjuje dvostrukim podcrtavima: __. 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 napuniti 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: Kako biste stvorili dumper funkcije koje se mogu koristiti s oba LLDB i GDB backenda, izbjegavajte izravan pristup imenim 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 podcrtava). 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 ne postoji, 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 format nije zajamčeno stabilan, snažno se preporučuje ne generirati format žice izravno, već koristiti sloj apstrakcije klasa Python Dumper, posebice samu klasu Dumper te apstrakcije Dumper:Value i Dumper:Type. Oni 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 otklanjanja pogrešaka za postavljanje poziva funkcije func koja vraća rettype na vrijednost navedenu pomoću value i za izlazak rezultirajućeg 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 pogreške. Međutim, trebali bi se koristiti samo u kontroliranom okruženju i samo ako ne postoji drugi način za pristup podacima, iz sljedećih razloga:

    • Izravna izvedba koda je opasna. Izvršava nativni kod s privilegijama procesa pod istragom, š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 adresi address.
  • putSubItem(self, component, value) - Ekvivalentno:
    with SubItem(self, component):
        self.putItem(value)

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

    except RuntimeError:
        d.put('value="<invalid>",type="<unknown>",numchild="0",')
  • 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 navedenih 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 podrazumijevanim tipom djeteta roditelja ili je putType već pozvan za trenutni element s višom vrijednošću priority.
  • putBetterType(self, type) - Poništava zadnje zabilježeno type.
  • putExpandable(self) - Obavještava o postojanju podređenih stavki za trenutnu vrijednost. Zadano nema podređenih stavki.
  • putNumChild(self, numchild) - Obavještava o postojanju (numchild > 0) ili nepostojanju 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 se zadovoljio zahtjev da sadrži samo alfanumeričke znakove. Parametar encoding je niz u obliku codec:itemsize:quote, gdje codec može biti bilo koji od sljedećih: latin1, utf8, utf16, ucs4, int ili float. itemsize određuje veličinu osnovne komponente objekta ako ona nije implicirana 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 - Označena 4-bajtna cjelobrojna vrijednost
      • I - Nesignirana 4-bajtna cjelobrojna vrijednost
      • h - Potpisana 2-bajtna cjelobrojna vrijednost
      • H - Neznakovani 2-bajtni cjelobrojni broj
      • b - Potpisana 1-bajtna cjelobrojna vrijednost
      • B - Bezpredznak vrijednost cjelobrojne varijable od 1 bajta
      • d - 8-bajtna IEEE 754 vrijednost s pomičnom zarezom
      • f - 4-bajtna IEEE 754 vrijednost pomičnog zareza
      • p - Pokazivač, 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

Klasa Dumper.Type

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

Objekti tipa, odnosno instanci klase Dumper.Type, mogu se stvoriti pomoću back-endova otklanjanja pogrešaka, obično evaluacijom informacija za otklanjanje pogrešaka ugrađenih u ili priloženih uz binarnu datoteku koja se otklanja, ili se mogu stvoriti u letu 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 za dereferenciranje pokazivača, 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 bazne 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 bitovima.

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 listu 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 tipa childType_ i childNumChild_ navodi po jedan broj. 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 suzbijen ako njegova adresa odgovara adresi 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 i Debugeri.

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.