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 Lokalne varijable i Izrazi.

Za razliku od GDB-ovih pretty printera i LLDB-ovih formatera podataka, pomoćnici za otklanjanje pogrešaka u Qt Creator u ne ovise o izvornom backendu za otklanjanje pogrešaka. To jest, isti se 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 u potpunosti 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 i izrazi u kartici Debugera

Ako primate poruke o pogreškama o primanju signala pri korištenju GDB-a, možete odrediti GDB naredbe za obradu tih signala. 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, već samo dodavanje 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 pogrešaka (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, 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 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 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, gdje je NS::Foo klasa ili predložak klase koji se ispituje. Imajte na umu da se operator za rješavanje opsega :: zamjenjuje dvostrukim podcrtavima: __. Mogući su 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: Kako biste stvorili dumper funkcije koje se mogu koristiti s oba LLDB i GDB backenda, 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ćne funkcije 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ćne funkcije 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 koje odgovara položaju prikaza objekta u pogledu. Ako ono 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 i 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 pomoćne funkcije:

  • putItem(self, value) - Glavna funkcija koja izravno obrađuje osnovne tipove, reference, pokazivače i enumove, 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 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 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 pozivima funkcija ugniježđenih u catch-klausuli se uhvate i sav izlaz proizveden pozivom 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) - 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='', po želji praćenu poljem valueencoding=''. value mora biti konvertibilan 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 oblika 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 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 - Bezpredznak vrijednost cjelobrojne vrijednosti od 8 bajtova
      • i - Potpisana 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 - 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 ciljanom 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 otklonika, 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 de-referencirati 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 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 ona 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 od podataka ove vrijednosti. Prihvatljivi obrasci su isti kao i za Dumper.createType.
  • dynamicTypeName(self) - Pokušava dohvatiti naziv dinamičke vrste 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 neinkcijalizirani ili oštećeni. Za uredno oporavljanje 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 ( childType_ i childNumChild_ ) navodi po jedan tip. Ako je naveden parametar maxNumChild, prikazat će se samo taj broj 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 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 jednostavnije 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 otklanjanje pogrešaka.

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.