Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Windebug User Manual
Windebug User Manual
Manuale di uso
Windebug è un debug con interfaccia grafica, basato sulle funzioni del debugger Gnu-GDB, utilizzabile per
programmi sviluppati con Proteus, su piattaforme:
ARM7-DTMI (V4L,V4C…)
Cortex M3 (V7,V8,V10,Pineapple…)
Cortex M4 (Vxx DSP)
Cortex A53 (Sistema T, Raspberry Pi2-Pi3-Pi4 con sistema operativo LINUX-ARM Raspbian
Jessie/Stretch/Buster)
68XX (PC con sistema operativo Windows XP/Vista/7/8/10)
- Si può debuggare il codice dell’ ultima versione compilata del programma. Se si fanno modifiche
occorre ricompilare e il debug non funziona su eseguibili precedenti, in quanto le linee di programma
non corrispondono più agli indirizzi di memoria.
- Si può lanciare il debug al di fuori di Proteus, ma occorre che la directory del programma che si vuole
debuggare non sia stata spostata o rinominata dopo la compilazione.
- Non occorre l’ opzione di compilazione DEBUG. Se tale opzione viene settata l’ unica differenza è che
nel codice del source appare per ogni linea l’ indirizzo di memoria relativo, ma in tal caso la
compilazione è (inutilmente) molto più lenta.
- Non occorre l’ opzione di ottimizzazione ZERO, anche se con tale opzione l’ esecuzione passo-passo del
programma è più leggibile.
- Si possono mettere un numero illimitato di breakpoints sulle linee di programma.
- Si può avanzare linea per linea (step-out) o seguire il flusso del programma (step-in). In altre parole se
una linea di programma contiene una Call, con step-in si entra nella call, mentre con step-out la call
viene eseguita in modo silenzioso e il debug si ferma alla riga successiva.
- Si possono esaminare i valori delle variabili cliccando sulla variabile nel listato del source.
- Si può esaminare ed eventualmente mettere dei breakpoints sul codice di tutti i sorgenti del
programma, comprese le librerie usate dal programma.
- Si può esaminare il back-trace (lo stack delle chiamate fino al punto di arresto in corso) e visualizzarne il
source (con il click del mouse destro)
- Si può avere la lista dei threads attualmente attivi.
- Si può fare una lista di variabili che verranno automaticamente visualizzate ad ogni break e ad ogni
step.
- Si può visualizzare la linea di programma in cui una variabile viene definita (con il click del mouse
destro)
- Si può avere una lista di tutte le occorrenze di una variabile, e visualizzarne il source (con il click del
mouse destro)
- Si può visualizzare il contenuto di un’ area di memoria
- Per i programmi ARM, Cortex e Linux è necessario per il debug un collegamento Ethernet o Wi-Fi.
Pur essendo WinDebug un unico programma, vi sono alcune differenze nelle funzionalità del
debug tra l’ esecuzione del debug per un programma ARM-CORTEX rispetto ad un programma
LINUX-WINDOWS.
- Il debug è compatibile con ogni versione del bios ARM, mentre per la versione CORTEX, il deve
essere con data uguale o successiva al 01-07-2020
- Si può debuggare un programma che sta già girando, senza interromperlo, e un breakpoint ferma
solo il task su cui è eseguito.
- Debuggando un programma fermo per un errore (TASK xx FAULT) il programma mostra la linea su
cui è avvenuto l’ errore, e si possono visualizzare i valori delle variabili e il back-trace dello stack che
ha portato all’ errore. Il debug può essere eseguito anche dopo che il programma si è bloccato, nel
qual caso il debug deve essere lanciato fuori da Proteus.
- Lanciando il debug da Proteus, il programma, se non già in esecuzione, viene automaticamente
caricato sulla periferica, tutti i breakpoints vengono cancellati e il programma è stoppato all’ inizio
del main.
- Tutti i comandi sono attivi anche quando il programma non è fermo su un breakpoint.
- Si possono mettere breakpoints multipli e contemporanei su task diversi.
- Si può visualizzare lo stato dei singoli task, i relativi tempi di esecuzione e i semafori associati.
- Nelle versioni Windows e Linux il programma viene lanciato e stoppato all’ inizio del main,
pertanto il programma non deve essere in esecuzione quando si lancia il debug.
- Nella versione Linux il programma deve essere precedentemente stato inviato alla periferica.
- Un breakpoint ferma tutti i threads del programma.
- Quando il programma sta girando non si possono eseguire comandi dal debug (solo dopo un break
o uno step)
- Quando il programma sta girando si può fermare con uno stop (Linux) o premendo Esc con il
cursore sulla finestra del programma (Windows).
- Si possono eseguire step fino alla fine di un loop o fino alla fine della funzione.
- Si possono visualizzare i valori delle variabili locali della funzione su cui è avvenuto il breakpoint
- Si possono creare breakpoints sul cambiamento del valore di una variabile, o della sua scrittura, o
della sua lettura (watchpoints)
- Si possono creare breakpoints condizionati (break if …)
- Si possono creare breakpoints e watchpoints che non interrompono l’ esecuzione del programma,
ma semplicemente stampano una stringa creata con un printf() contenente valori di variabili od
altro, e continuano l’ esecuzione.
- È possibile cambiare il valore di una o più variabili quando il programma è fermo.
- È possibile continuare il programma da un punto diverso da quello in cui si è fermato.
- È possibile creare liste di comandi, salvarle con un nome, caricarle ed eseguirle.
- È possibile visualizzare un’ intera struttura, ed i valori di tutti i campi relativi.
- È possibile visualizzare i registri della CPU ed il codice assembler della linea su cui il programma è
fermo, oppure il codice assembler dell’ intera funzione.
Alcune note sul funzionamento di Windebug.
Il compilatore gnu-gcc produce un eseguibile di tipo ELF, indipendentemente dalla cpu target.
Proteus usa 5 diversi compilatori gcc:
Compilando con opzione –g (oppure –ggdb) l’ eseguibile contiene tutte le informazioni necessarie a gdb per gesire la
sessione di debug dell’ eseguibile.
Il programma gdb.exe selezionato gira sempre sul PC con cui è stato compilato il programma, in una shell di
DOS in background, collegato con Windebug con 2 pipes, una di lettura e una di scrittura.
GDB è un programma a linee di testo, che accetta i comandi da tastiera (stdin) e stampa le risposte nella
finestra di DOS in cui gira (stdout).
Stdin è rediretto su una pipe di output di Windebug, e stdout è rediretto su una pipe di input di Windebug,
così Windebug ha il pieno controllo di gdb e si sostituisce all’ utilizzatore da console.
- La tastiera e lo schermo del PC (stdin e stdout) per ricevere i comandi e mostrare le risposte (nel
nostro caso sostituite dalle due pipes da e verso Windebug)
- L’ eseguibile, che viene mandato in esecuzione e che contiene le informazioni relative ai files del
sorgente, alle librerie e all’ indirizzo di memoria del codice eseguibile e delle variabili.
- I sorgenti (.C, .H, .CPP …) che debbono trovarsi nelle directory in cui erano al momento della
compilazione.
- Un hardware su cui far girare il programma, che può essere il PC stesso (programma per Windows),
oppure un hardware esterno, collegato via ethernet o wi-fi, su cui gira un server (gdbserver), è il
caso di programma LINUX.
- Per i programmi per ARM e CORTEX, non esiste un server gdb, per cui i comandi diretti verso il
server e le relative risposte vengono deviati verso un client UDP sulla porta 0x2764, che colloquia
con il relativo server sulla macchina su cui gira il programma. Si tratta dei comandi RUN, STEP-IN,
STEP-OUT, read-ram e read status e delle relative risposte. Tutti gli altri comandi vengono eseguiti
da GDB leggendo i dati presenti sul PC, senza bisogno di consultare l’ hardware esterno.
- Una connessione TCP sulla porta 0x2700 e una connessione UDP sulla porta 0x2764 (caso ARM-
CRTEX)
- Una connessione TCP sulla porta 1234 verso gdbserver e una connessione UDP sulla porta 0x2764
verso console2 (caso LINUX)
All’ avvio viene esaminato il tipo di eseguibile (.exe per windows, .bin per linux, .elf per arm-cortex).
Eseguibile PC:
- Viene lanciato in background il processo GDB per windows, con 2 pipes rispettivamente per stdin e
stdout, collegate con windebug
- Dal processo GDB viene lanciato l’ eseguibile .exe, stoppandolo su winmain.
- Windebug controlla il processo GDB tramite le 2 pipes, inviando i comandi ed attendendo le
risposte.
- Ad ogni comando è attesa una risposta immediata, salvo per i comandi run, continue e step, per cui
la risposta avviene quando l’ azione è eseguita ed il programma è fermo.
- Ogni risposta (che può essere multi linea) termina con la linea “(gdb)”
- Le risposte vengono interpretate e il loro contenuto visualizzato nei campi relativi.
Eseguibile LINUX:
- Viene lanciato in background il processo GDB per linux, con 2 pipes rispettivamente per stdin e
stdout, collegate con windebug.
- Viene lanciato il gdbserver con un comando diretto verso console2.
- Dal processo GDB viene lanciato il collegamento con gdbserver, comunicandogli la porta TCP di
colloquio (porta 1234).
- Dal processo GDB viene lanciato l’ eseguibile, stoppandolo su main.
- Windebug controlla il processo GDB tramite le 2 pipes, inviando i comandi ed attendendo le
risposte. Le richieste che implicano una modifica di esecuzione o la lettura di variabili dell’
eseguibile, vengono inoltrate al gdbserver e la risposta arriva da esso, prima che il gdb la visualizzi
su stdout.
- Ad ogni comando è attesa una risposta immediata, salvo per i comandi run, continue e step, per cui
la risposta avviene quando l’ azione è eseguita ed il programma è fermo.
- Ogni risposta (che può essere multi linea) termina con la linea “(gdb)”
- Le risposte vengono interpretate e il loro contenuto visualizzato nei campi relativi.
Eseguibile ARM-CORTEX:
- Viene lanciato in background il processo GDB per arm-cortex, con 2 pipes rispettivamente per stdin
e stdout, collegate con windebug.
- Windebug invia il programma alla macchina in remoto, se il programma non è già in esecuzione.
- Da Windebug, se il programma non sta già girando, viene lanciato l’ eseguibile, stoppandolo su
main.
- Windebug controlla il processo GDB tramite le 2 pipes, inviando i comandi ed attendendo le
risposte. Le richieste che implicano una modifica di esecuzione o la lettura di variabili dell’
eseguibile, vengono inoltrate direttamente da Windebug ramite UDP sulla porta 0x2764 e la
risposta arriva da esso e viene visualizzata bypassando GDB.
- Ad ogni comando è attesa una risposta immediata, salvo per i comandi run, continue e step, per cui
la risposta avviene quando l’ azione è eseguita ed il task relativo è fermo.
- Ogni risposta (che può essere multi linea) termina con la linea “(gdb)”
- Le risposte vengono interpretate e il loro contenuto visualizzato nei campi relativi.
LE FUNZIONI DI Windebug
Figura 1:
Lanciando Windebug
esternamente da Proteus
appare una finestra che
consente di scegliere il
programma da debuggare e
il tipo di hardware su cui
gira.
Figura 2:
Se l’ hardware è Linux o
Cortex viene tentato il
collegamento con la
periferica. Se l’ indirizzo IP
non è corretto occorre
impostarlo e premere il
bottone Connect. L’ indirizzo
IP verrà memorizzato per le
volte successive.
Figura 3:
Se l’ hardware è di tipo arm-cortex il debugger tenta di
inviare l’ eseguibile alla periferica.
Se il programma è già in funzione appare un messaggio di
errore e si può uscire dalla funzione di invio premendo il
bottone Exit.
Se Windebug è lanciato fuori da Proteus le procedure di
collegamento e di invio programma debbono essere
effettuate dall’ operatore premendo i relativi bottoni.
Figura 4:
Dopo la procedura di avvio, necessaria per programmi Linux e arm-cortex per collegarsi con l’ hardware su
cui gira il programma, appare la videata principale, e il programma effettua automaticamente un
breakpoint all’ inizio del main.
La colonna di destra contiene la lista in ordine alfabetico dei sources del programma.
Cliccando su un elemento della lista viene visualizzata la relativa pagina, su cui possiamo ad esempio
mettere dei breakpoints o leggere il valore delle variabili.
Con un doppio click sulla lista, vengono visualizzati i nomi di tutti i sources usati dal programma, comprese
le librerie di sistema.
dovre
Breakpoints:
Per mettere un breakpoint selezionare con un doppio click la linea del source relativa. Dovrebbe apparire
un punto rosso a sinistra del numero della linea. Se ciò non avviene significa che la linea non contiene
codice eseguibile e quindi non può essere associata ad un breakpoint
Con un nuovo doppio click si disattiva il breakpoint.
La prima colonna in alto di sinistra contiene la lista dei breakpoints (attivi e non), e cliccando con il pulsante
destro del mouse su un elemento della lista, la finestra centrale si sposta sul source del breakpoint.
Figura 5:
Vi sono altri metodi per attivare un breakpoint:
Premendo il bottone Breakpoint (cerchio rosso)
appare una finestra che consente di impostare un
breakpoint su una linea del source attualmente
visualizzato. La finestra consente di imporre delle
condizioni al breakpoint, e di associare una serie di azioni da eseguire all’ occorrenza dello stesso.
La finestra consente inoltre di inserire dei watchpoints, ovvero dei breakpoints non legati all’ esecuzione di
una linea di programma ma al cambiamento del valore di una variabile o alla chiamata di una funzione.
Anche ad un watchpoint può essere associata una serie di azioni da eseguire.
Figura 6:
Un altro metodo per inserire un
breakpoint o un watchpoint è quello
di aprire la console di GDB e
impostare sul pannello superiore il
comando o la serie di comandi gdb da
eseguire, quindi premere Execute.
Le serie di comandi possono essere
salvate e ricaricate all’ occorrenza.
GDB ha un set di oltre 900 tipi di
comandi che possono essere eseguiti
da console. Per una lista completa
consultare il manuale PDF di GDB.
I pannelli di visualizzazione.
6
8
1 2 3
5 6
Figura 7:
1. Messages
2. Variables
3. Backtrace
4. Ram
5. Found
6. Threads
7. Local Vars
8. BreakPoint
Messages
Pannello contenente messaggi generici (non importante)
Variables
Mostra il valore delle variabili aggiunte al pannello con il tasto Add (il nome è quello mostrato nel campo
Search in alto a destra (che viene settato cliccando sul nome di una variabile nel pannello 2).
I valori vengono aggiornati all’ occorrenza di un breakpoint o di uno step.
Solo per ARM-CORTEX si può chiedere un aggiornamento continuo selezionando il flag Refresh.
Nel caso in cui il nome di una variabile sia il nome di una struttura, vengono mostrati i nomi e i valori di tutti
gli elementi della struttura. Per ulteriori dettagli vedere l’ appendice C.
Backtrace
Mostra la lista dei nexting delle chiamate che hanno portato al breakpoint.
L’ elemento 0 è la riga del breakpoint stesso.
La riga 1 e’ la riga della chiamata alla riga 0 ecc…
Cliccando con il tasto destro del mouse su un elemento della lista, il pannello 2 mostra il file relativo (se non
è un file di sistema) puntando alla chiamata della funzione successiva.
Ram
Scrivendo nel campo address un indirizzo (0x + 8 cifre esadecimali) viene mostrato (se accessibile) il
contenuto della memoria a partire dall’ indirizzo specificato.
Found
Mostra tutte le occorrenze, in tutti i files della lista delpannello 3, della stringa del campo Search.
Anche in questo caso, cliccando con il tasto destro del mouse su una linea della lista, il pannello 2 mostra il
file relativo puntando alla linea relativa.
Threads
Mostra la lista di tutti i threads attivi dell’ applicazione, evidenziando con un asterisco quello del breakpont.
Local Vars
Mostra il nome ed il valore di tutte le variabili locali della funzione che ha generato il breakpoint, con il
valore aggiornato al momento del breakpoint (o dello step). Le variabili locali posson essere aggiunte anche
al pannello delle variabili, nel qual caso compaiono nella lista solo quando siamo dentro la funzione in cui
sono definite.
BreakPoint
Mostra il numero del breakpoint attuale e il nome del file e della riga in cui è avvenuto.
A B C D E F G H I J K L M N O P
A – Chiusura del debug e uscita da programma. I programmi Linux e Windows si chiudono, mentre i programmi ARM-
CORTEX continuano l’ esecuzione
B – Collegamento ethernet/wifi con la periferica. Attivo solo per programmi ARM-CORTEX con Debug lanciato
esternamente da Proteus. Negli altri casi il collegamento è effettuato automaticamente all’ avvio di Windebug.
C – Invio del programma alla periferica. Attivo solo per programmi ARM-CORTEX con Debug lanciato esternamente da
Proteus. Negli altri casi il collegamento è effettuato automaticamente all’ avvio di Windebug.
D – Run/Continue. Lancia il programma all’ inizio o ne riprende l’ esecuzione dopo un breakpoint. È consigliabile di
settare gli opportuni breakpoins prima di utilizzare questa funzione, in quanto quando il programma è in esecuzione la
barra dei comandi è inattiva (salvo il caso ARM-CORTEX).
E – Stop del programma. Attivo per programmi Linux e ARM-CORTEX. Per programmi Windows per arrestare il
programma selezionare con il mouse il programma in esecuzione e premere il tasto Esc.
F – Step-In. Avanza l’ esecuzione del programma eseguendo l’ istruzione C su cui è fermo. Se è selezionata la
visualizzazione del codice assembler il programma vanza di una sola istruzione assembler.
G – Step-Out. Avanza l’ esecuzione del programma fino al raggiungimento della linea di programma successiva. Non
utilizzare questa funzione quando il programma è fermo sull’ ultima linea di una funzione.
H – Step to end. Il programma avanza fino all’ uscita della funzione che sta eseguendo.
I – Step to exit loop. Se il programma si trova in un FOR o in un DO-WHILE il programma avanza fino all’ uscita dal
loop.
J – Apre la finestra di dialogo di costruzione di breakpoints (Figura 5). Questa funzione è utile per settare breakpoints
condizionati o watchpoints. Per settare un semplice breakpoint su una linea di programma è sufficiente un doppio
click con il bottone sinistro del mouse sulla linea di programma.
L – Apre la finestra di console GDB (figura 6) , nella quale possiamo eseguire tutti i comandi GDB (vedi appendice A)
N – Search. Scrivendo un nome in questa finestra, con i tasti M ed O il listato del pannelo 2 si ferma sulle varie
occorrenze del nome nel file corrente.Con il tsto P si cercano invece tutte le occorrenze del nome in tutti i files della
lista del pannello 2. Con un click sul pannello 2 sul nome di una variabile o di una funzione tale nome viene copiato
sulla finestra N.
Appendice A: Principali comandi GDB
- Settare bp
- Vedere bp settati
- Cancellare bp
- Disabilitare bp
- Riabilitare bp
- Settare wp
- Visualizzare wp
- Condizioni per i bp/wp
- Modificare/Aggiungere la condizione
- Cancellare la condizione
- Eseguire lo stop del programma solo dopo m volte che si e’ verificato il bp/wp
- Eseguire comandi in automatico quando si verifica lo stop per un bp
- Continuare l’esecuzione del programma
- Vedere il disassemblato
- Assegnare il valore ad una variabile
- Continuare ad un indirizzo diverso
- Ritornare da una funzione
- Chiamare funzioni
- Stampare il valore di una espressione
- Visualizzare il contenuto delle locazioni di memoria
- Settare una visualizzazione automatica
- Visualizzare le visualizzazioni automatiche settate
- Disabilitare le visualizzazioni automatiche settate
- Riabilitare le visualizzazioni automatiche settate
- Cancellare le visualizzazioni automatiche settate
- Vedere tutti i registri e i loro valori
- Esaminare la symbol-table
Settare bp:
Comando break (abbreviato b)
break nome_funzione
bp sulla funzione (solo se sono presenti le info di debug, o se avete usato labelz ;)
break +offset
break -offset
bp offset linee dopo/prima l’istruzione corrente
break *indirizzo
bp all’istruzione a indirizzo
break (niente)
bp all’istruzione successiva a quella corrente
bp condizionati:
break ... if condizione
stop solo se e’ valutata VERA la condizione
bp particolari:
tbreak ...
come break ma valido solo per uno stop, poi viene cancellato automaticamente
Vedere bp settati:
info breakpoints [n]
visualizza tutti i bp (o il bp numero n se indicato)
Indicazioni visualizzate:
Numero_bp | Tipo (bp/wp) | Disposizioni | Abilitato(y)/Disabilitato(n) | Indirizzo_bp |
Posizione_nel_sorgente
Cancellare bp:
Comando delete (abbreviato d)
delete [n]
cancella tutti i bp (o il bp numero n se indicato)
Comando clear (se si da il comando appena dopo che il programma si e’ appena fermato ad un bp
si
cancella il bp stesso)
clear [nome_funzione]
cancella il bp sulla prossima istruzione (o il bp su nome_funzione se indicato)
Disabilitare bp:
Comando disable (abbreviato dis)
disable [n]
disabilita tutti i bp (o il bp numero n se indicato)
Riabilitare bp:
Comando enable
enable [n]
riabilita tutti i bp (o il bp numero n se indicato)
enable once [n]
riabilita tutti i bp (o il bp numero n se indicato) ma al primo stop viene disabilitato
automaticamente
Settare wp:
Comandi
watch locazione
wp quando il programma scrive su locazione
rwatch locazione
wp quando il programma legge da locazione
awatch locazione
wp quando il programma scrive o legge locazione
Visualizzare wp:
info watchpoints
equivale a "info breakpoints"
Condizioni per i bp/wp:
Osservazioni:
- per i wp la condizione puo’ essere settata solo con il comando "condition"
- devono essere condizioni booleane
- viene fermato il programma solo se la condizione indicata e’ valutata vera
- e’ possibile negare la condizione anteponendo il simbolo ’!’ alla condizione (! not in C)
Modificare/Aggiungere la condizione
condition n condizione
aggiunge condizione al bp/wp numero n
Cancellare la condizione
condition n (niente)
cancella la condizione al bp/wp numero n (in realta’ setta la condizione a niente)
Eseguire lo stop del programma solo dopo m volte che si e’ verificato il bp/wp
ignore n m
setta il bp/wp numero n in modo che generi lo stop del programma solo dopo m volte che si e’
verificato il bp/wp stesso
Comando finish
finish
continua l’esecuzione del programma fino alla termianzione della funzione corrente e stampa il
valore di ritorno (se c’e’)
Vedere il disassemblato
Comando disassemble
disassemble
visualizza il sorgente assembly della funzione in cui si trova l’istruzione corrente
disassemble indirizzo
visualizza il sorgente assembly della funzione in cui si trova l’istruzione a indirizzo
disassemble ind_i ind_f
visualizza il sorgente assembly delle istruzioni dall’indirizzo ind_i (compreso) all’indirizzo ind_f
(escluso)
Chiamare funzioni
call nome_funzione
chiama la funzione nome_funzione
Esaminare i dati:
Stampare il valore di una espressione
Comando print (abbreviato p)
print[/f] espressione
visualizza il valore di espressione; se presente /f utilizza il formato indicato
Formati di visualizzazione
x intero esadecimale
d intero decimale
u intero decimale senza segno
intero ottale
t intero binario
a indirizzo
c carattere
f virgola mobile
Visualizzazione automatica
Settare una visualizzazione automatica
Comando display
display[/f] espressione
visualizza il valore di espressione; se /f e’ presente usa il formato indicato
Formati di visualizzazione
x intero esadecimale
d intero decimale
u intero decimale senza segno
intero ottale
t intero binario
a indirizzo
c carattere
f virgola mobile
i istruzione
s striga null-terminated
Se il formato e’ i o s
display[/f] indirizzo
visualizza il contenuto della locazionea indirizzo
Esaminare la symbol-table
info address simbolo
visualizza dove e’ memorizzato simbolo
whatis espressione
visualizza il tipo di dato di espressione
ptype nome_tipo
visualizza una descrizione del tipo di dato
ptype espressione
visualizza una descrizione di espressione; piu’ completo di whatis
info source
visualizza il nome del file sorgente attuale
info sources
visualizza tutti i file sorgenti con informazioni di debug
info functions [expr]
visualizza nome e tipo di dati di tutte le funzioni; se e’ presente expr, solo di quelle il cui nome
contiene expr
info variables [expr]
visualizza informazioni su tutte le varibili; se e’ presente expr, solo di quelle il cui nome contiene
expr
Appendice B: GDB su eseguibili ARM-CORTEX
Il debug per programmi ARM-CORTEX presenta alcune differenze rispetto al debug per programmi
Linux o Windows:
Ad esempio:
int x=100;
int *y=malloc(4);*y=200;
Le strutture, se contengono
numerosi campi, non
vengono interamente
visualizzate cliccando sul
loro nome.
Per una visualizzazione
completa occorre
aggiungere il loro nome alla
lista delle variabili da
visualizzare.
Se una struttura contiene
altre strutture, se la casella
Next è attivata, appare l’
intero albero della struttura,
altrimenti vengono
visualizzati solo i valori della
struttura principale.
I valori delle variabili possono essere visualizzati sotto forme diverse.
Prendiamo come esempio il seguente programma:
COM *mycom=COM1;
char *pp1=0;
char pp2[40];
short sss[10];
float fff1;
double ddd1;
void prova(void)
{
if (pp1==0) pp1=calloc(1,40);
sprintf(pp1,"12345");
sprintf(pp2,"67890");
fff1=3.1415926539;
ddd1=fff1 * 2.;
com_open(mycom,9600);
s2.s1.a1=1;
s2.a2=2;
for (int i=0;i<10;i++)
{
sss[i]=i*100;
lll[i]=i*1000;
}
strcpy(s2.s1.b1,"aaaa");
strcpy(s2.b2,"bbbb");
s2p->s1.a1=3;
s2p->a2=4;
strcpy(s2p->s1.b1,"cccc");
strcpy(s2p->b2,"dddd");
}
Se vogliamo visualizzare i valori dei char[] come valori numerici anziché in ascii, selezioniamo View mode=Hex (oppure
=Dec). Notare che in questo modo pp1 (che è un puntatore) visualizza il valore del puntatore anziché il contenuto,
mentre pp2, che è un array di bytes, continua a visualizzare il contenuto.
Se vogliamo visualizzare in forma multi-linea (ad es. se vogliamo vedere l’ intera struttura mycom, che non entra nella
finestra di visualizzazione, selezioniamo Multiline Array.
Volendo vedere nei dettagli anche le strutture di livello superiore di mycom, potremmo selezionare l’ opzione
Recursive structures, che dà una lista dettagliata ma estremamente lunga della variabile mycom:
mycom = {
+ open = 0
+ mode = 0
+ baud = 9600
+ subrx = 0x0
+ subtx = 0x0
+ rx0 = 0
+ rx1 = 0
+ tx0 = 0
+ tx1 = 0
+ rxbuff = 0x0
+ txbuff = 0x0
+ rbuff = 0x0
+ rbufn = 0
+ rbufp = 0
+ rx_sleep = 0
+ or = {
++ Internal = 0
++ InternalHigh = 0
++ {
+++ {
++++ Offset = 0
++++ OffsetHigh = 0}
+++ Pointer = 0x0}
++ hEvent = 0x0}
+ tbuff = 0x0
+ tbufn = 0
+ tbufp = 0
+ tx_sleep = 0
+ ow = {
++ Internal = 0
++ InternalHigh = 0
++ {
+++ {
++++ Offset = 0
++++ OffsetHigh = 0}
+++ Pointer = 0x0}
++ hEvent = 0x0}
+ rxstatus = 0
+ txstatus = 0
+ rxchk = 0
+ txchk = 0
+ rxsize = 0
+ txsize = 0
+ centr = 0
+ perif = 0
+ echo = 0
+ txrun = 0
+ enabled = 0
+ parity = 0
+ stops = 0
+ errors = 0
+ NameCom = "COM1" '0x00'
+ protocol = 0x0
+ hCom = 0xffffffff
+ ctmoNew = {
++ ReadIntervalTimeout = 0
++ ReadTotalTimeoutMultiplier = 0
++ ReadTotalTimeoutConstant = 0
++ WriteTotalTimeoutMultiplier = 0
++ WriteTotalTimeoutConstant = 0}
+ ctmoOld = {
++ ReadIntervalTimeout = 0
++ ReadTotalTimeoutMultiplier = 0
++ ReadTotalTimeoutConstant = 0
++ WriteTotalTimeoutMultiplier = 0
++ WriteTotalTimeoutConstant = 0}
+ dcb = {
++ DCBlength = 0
++ BaudRate = 0
++ fBinary = 0
++ fParity = 0
++ fOutxCtsFlow = 0
++ fOutxDsrFlow = 0
++ fDtrControl = 0
++ fDsrSensitivity = 0
++ fTXContinueOnXoff = 0
++ fOutX = 0
++ fInX = 0
++ fErrorChar = 0
++ fNull = 0
++ fRtsControl = 0
++ fAbortOnError = 0
++ fDummy2 = 0
++ wReserved = 0
++ XonLim = 0
++ XoffLim = 0
++ ByteSize = 0
++ Parity = 0
++ StopBits = 0
++ XonChar = 0
++ XoffChar = 0
++ ErrorChar = 0
++ EofChar = 0
++ EvtChar = 0
++ wReserved1 = 0}}