Come hanno eseguito il debug degli errori di segmentazione prima della memoria protetta?


20

Ora, quando commetto un errore di programmazione con i puntatori in C, ricevo un buon errore di segmentazione, il mio programma si arresta in modo anomalo e il debugger può persino dirmi dove è andato storto.

Come hanno fatto nel momento in cui la protezione della memoria non era disponibile? Riesco a vedere un programmatore DOS che armeggia e si blocca l'intero sistema operativo quando ha fatto un errore. La virtualizzazione non era disponibile, quindi tutto ciò che poteva fare era riavviare e riprovare. È andata davvero così?


4
Sì, è andata così. Si è verificato un riavvio casuale del computer e si è verificato spesso. La protezione della memoria è una cosa meravigliosa :)
Rocklan,

7
Quando non si dispone di memoria protetta, non esiste un errore di segmentazione. Ovviamente, anche se hai memoria protetta, puoi comunque ostruire il tuo spazio; il sistema operativo non se ne preoccupa.
Blrfl,

3
Anche ora molti errori del puntatore non causano un buon segfault.
CodesInChaos

1
Al momento del DOS, la memoria protetta esisteva già in altri sistemi operativi.
mouviciel,

Risposte:


36

Riesco a vedere un programmatore DOS che armeggia e si blocca l'intero sistema operativo quando ha fatto un errore.

Sì, è praticamente quello che è successo. Sulla maggior parte dei sistemi con mappe di memoria, la posizione 0 era contrassegnata come non valida, in modo che i puntatori null potessero essere facilmente rilevati, poiché quello era il caso più comune. Ma ci sono stati molti altri casi e hanno causato il caos.

A rischio di sembrare un geezer, dovrei sottolineare che l'attuale attenzione al debug non è la via del passato. In passato era stato fatto molto più sforzo per scrivere programmi corretti, piuttosto che per rimuovere bug da programmi errati. Parte di ciò era perché quello era il nostro obiettivo, ma molto perché gli strumenti rendevano le cose difficili. Prova a scrivere i tuoi programmi su carta o su schede perforate, non in un IDE e senza il beneficio di un debugger interattivo. Ti dà un gusto per la correttezza.


3
In realtà, speravo che "vecchi geezers" avrebbero risposto alla mia domanda. Niente batte l'esperienza di prima mano. Grazie.
Bart Friederichs,

6
Prova a scrivere codice quando l'hardware è disponibile per il debug ogni notte dalle 02:00 alle 06:00, supponendo ovviamente che il tuo collega non lo abbia prenotato per la sua sessione di debug.
Salterio

@MSalters Indeed! Al mio primo lavoro, potremmo anche prenotare le slot domenica dal 0700 al 1900 - una vera delizia, lascia che ti dica :-)
Ross Patterson,

2
Ricordo di aver scritto il mio primo programma su carta viaggiando a casa dall'università. Il giorno dopo, quando ho potuto inserirlo e eseguirlo, è stato impeccabile ;-)
Jan Doggen,

1
@ JanDoggen, lo stesso per me. Quando hai una sola prova, fai che quella prova conti davvero.
nalply

23

Ai miei tempi, non avevamo la protezione della memoria e tutta quella faccenda elegante! Abbiamo usato printf per determinare dove eravamo nel programma e ci è piaciuto !

Sebbene in tutta serietà, di solito significava che eravamo solo più attenti. Laddove viene chiamato malloc, è necessario che ci sia un altro posto libero nel programma e tale controllo è stato rigoroso perché in caso di problemi, come hai chiaramente sottolineato, i guasti di segmentazione non sono errori utili.

Nel caso di tali errori, la cosa migliore da fare è cercare di capire quando si verificano tali errori di segmentazione (usando printf) e, osservando il codice, determinare perché l'accesso alla memoria in quel punto non era valido e procedere all'indietro da lì.

In sostanza, la stessa cosa accade oggi, tranne per il fatto che utilizziamo i debugger per determinare quando si verificano errori, ma devi ancora capire perché è successo e non è sempre così semplice come trovare la linea in cui si è verificato l'errore. Gli errori causano errori come una reazione a catena e se in quei giorni eri un programmatore C, trascorrevi il 20% del tuo tempo a programmare e il resto del tempo a strappare i capelli per correggere i bug.


2
Libera i Malloc!
Chris,

1
Di tanto in tanto, anche oggi, anche lo stack di chiamate e lo stato variabile sono completamente inutili per determinare cosa diavolo è andato storto e come risolverlo. Questo è particolarmente vero se si dispone di software complessi con un gran numero di stati possibili, alcuni dei quali interdipendenti e altri reciprocamente esclusivi. Una sola scrittura vagante ovunque e un'asserzione omessa per il presupposto garantito possono portarti lì.
un CVn

1
@ MichaelKjörling, penso che per quanto riguarda la scoperta di errori nei programmi, abbiamo progredito solo per ciò che riguarda la ricerca del trigger di errore, ma abbiamo ancora miglia da percorrere per scoprire la causa di questi errori. Le affermazioni aiutano sicuramente a mantenermi sano di mente. :)
Neil,

6

bene ..

un segfault è davvero un buon indicatore del fatto che qualcosa non va, ma devi ancora trovare la causa principale. Quindi, se fai la domanda come trovi la causa principale rispetto alla risposta non è molto diversa oggi rispetto a allora. Naturalmente le lingue e gli strumenti sono diventati più facili da lavorare, ma il taktik generale è lo stesso:

  • la registrazione aiuta a trovare l'area in cui si trova il problema. La ricerca binaria printf ne è una forma.
  • debug, step by step, break points e watch
  • refactoring per ottenere una migliore comprensione
  • fissando il codice
  • guarda il dump della memoria / core
  • alimentandolo con dati diversi
  • mostrandolo ad altre persone
  • passare a una lingua senza puntatori (e una nuova serie di problemi) ...

A un livello più astratto hai tre approcci: 1. lavora con il codice 2. guarda il programma mentre è in esecuzione 3. guarda i risultati dopo aver fatto qualcosa di stupido

tra l'altro un errore del puntatore non deve creare un segfault.

Come programmatore Amiga ho usato praticamente tutto. E sì, riavvia dove pratica comune.


4

Su IBM 360, eseguendo lavori batch Fortran, abbiamo usato per ottenere dump core esadecimali. Una simile discarica potrebbe essere spessa un centimetro di carta per stampante verde e bianca a ventaglio. Direbbe quali erano i registri e da lì potremmo tornare indietro e capire cosa stava facendo il programma. Potremmo trovare ogni subroutine e capire dove ha memorizzato il suo indirizzo di ritorno, in modo da poter vedere il contesto. Sarebbe utile avere un elenco degli assemblatori del programma.


2

Una volta stavo lavorando alla correzione di bug su un allora famoso software di presentazione di Windows 3.1.

Ho avuto un bug che, quando si è verificato, ha causato la schermata blu della morte.

Il bug si verificava solo quando un certo ciclo era stato eseguito più di 1000 volte. Ho usato le funzionalità avanzate del debugger per far passare un punto di interruzione 1000 volte e poi ho esaminato attentamente il programma. Ogni volta che sono andato troppo lontano o ho saltato una chiamata di funzione che conteneva il bug Windows Blue Screened.

Alla fine, dopo diversi giorni di lavoro, l'ho ridotto a una funzione che stava esaurendo la memoria e invece di visualizzare un messaggio di errore, ho aggiunto il messaggio di errore a un buffer. Con ogni iterazione successiva ha eliminato più memoria fino a quando qualcosa di cruciale è stato sovrascritto e Windows è stato eliminato.

Le capacità di debugging e la perseveranza sono state la soluzione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.