¿Cómo depuraron las fallas de segmentación antes de la memoria protegida?

20

Ahora, cuando cometo un error de programación con punteros en C, aparece un buen error de segmentación, mi programa se bloquea y el depurador puede incluso decirme dónde salió mal.

¿Cómo hicieron eso en el momento en que la protección de memoria no estaba disponible? Puedo ver un programador de DOS jugando y bloqueando todo el sistema operativo cuando cometió un error. La virtualización no estaba disponible, por lo que todo lo que pudo hacer fue reiniciar y volver a intentar. ¿Realmente fue así?

Bart Friederichs
fuente
44
Sí, así fue. Se produjo un reinicio aleatorio de la computadora, y sucedió a menudo. La protección de la memoria es algo maravilloso :)
Rocklan
77
Cuando no tiene memoria protegida, no existe una falla de segmentación. Por supuesto, incluso si tiene memoria protegida, aún puede golpear su propio espacio; al sistema operativo simplemente no le importa.
Blrfl
3
Incluso ahora, muchos errores de puntero no causan un buen defecto de seguridad.
CodesInChaos
1
En el momento de DOS, la memoria protegida ya existía en otros sistemas operativos.
Mouviciel

Respuestas:

36

Puedo ver un programador de DOS jugando y bloqueando todo el sistema operativo cuando cometió un error.

Sí, eso es más o menos lo que pasó. En la mayoría de los sistemas que tenían mapas de memoria, la ubicación 0 se marcaba como no válida, por lo que los punteros nulos podían detectarse fácilmente, porque ese era el caso más común. Pero hubo muchos otros casos y causaron estragos.

A riesgo de sonar como un geezer, debo señalar que el enfoque actual en la depuración no es el del pasado. Anteriormente se hizo mucho más esfuerzo para escribir programas correctos, en lugar de eliminar errores de programas incorrectos. Algo de eso fue porque ese era nuestro objetivo, pero mucho fue porque las herramientas hicieron las cosas difíciles. Intente escribir sus programas en papel o en tarjetas perforadas, no en un IDE y sin el beneficio de un depurador interactivo. Te da gusto por lo correcto.

Ross Patterson
fuente
3
De hecho, esperaba que "viejos amigos" respondieran a mi pregunta. Nada supera la experiencia de primera mano. Gracias.
Bart Friederichs
66
Intente escribir código cuando el hardware esté disponible para la depuración todas las noches de 02:00 a 06:00, suponiendo, por supuesto, que su colega no lo haya reservado para su sesión de depuración.
MSalters
@MSalters De hecho! En mi primer trabajo, también podríamos reservar tragamonedas el domingo de 0700 a 1900 - un verdadero placer, déjame decirte :-)
Ross Patterson
2
Recuerdo haber escrito mi primer programa en papel viajando a casa desde la universidad. Al día siguiente, cuando pude golpearlo y ejecutarlo, fue perfecto ;-)
Jan Doggen
1
@ JanDoggen, lo mismo para mí. Cuando solo tienes un intento, haces que ese intento realmente cuente.
finalmente
23

En mi día, no teníamos protección de memoria y todo ese negocio elegante. Usamos printf para determinar en qué parte del programa estábamos , ¡ y nos gustó !

Aunque con toda seriedad, generalmente significaba que teníamos más cuidado. Cuando se llama a malloc, tenía que haber un programa gratuito en algún otro lugar del programa, y ​​dicha verificación fue rigurosa porque en el caso de un problema, como ha señalado claramente, las fallas de segmentación no son errores útiles.

En el caso de tales errores, lo mejor que puede hacer es tratar de comprender cuándo ocurren tales fallas de segmentación (usando printf) y, mirando el código, determinar por qué el acceso a la memoria en ese punto no era válido y trabajar hacia atrás desde allí.

En esencia, lo mismo sucede hoy, excepto que usamos depuradores para determinar cuándo ocurren los errores, pero aún debe comprender por qué sucedió, y no siempre es tan simple como encontrar la línea en la que ocurrió el error. Los errores causan errores como una reacción en cadena, y si eras un programador de C en esos días, pasabas el 20% de tu tiempo codificando y el resto del tiempo arrancándote el pelo arreglando errores.

Neil
fuente
2
¡Libera a los Mallocs!
Chris
1
De vez en cuando, incluso hoy, incluso la pila de llamadas y el estado variable son completamente inútiles para determinar qué diablos salió mal y cómo solucionarlo. Ese es el caso particularmente si tiene un software complejo con una gran cantidad de estados posibles, algunos de los cuales son interdependientes y otros mutuamente excluyentes. Una sola escritura perdida en cualquier lugar y una afirmación omitida para la precondición garantizada pueden llevarlo allí.
un CVn
1
@ MichaelKjörling, creo que en lo que respecta a descubrir errores en los programas, hemos progresado solo en lo que respecta a encontrar el desencadenante de error, pero todavía tenemos mucho camino por recorrer para descubrir la causa de estos errores. Las afirmaciones ayudan a mantenerme cuerda, seguro. :)
Neil
6

bien ..

un segfault es un buen indicador de que algo está mal, pero aún tiene que encontrar la causa raíz. Entonces, si hace la pregunta, ¿cómo encuentra la causa raíz que la respuesta no es muy diferente hoy de lo que era entonces? Por supuesto, los idiomas y las herramientas se volvieron más fáciles de trabajar, pero el taktik general es el mismo:

  • el registro ayuda a encontrar el área donde está su problema. La búsqueda binaria printf es una forma de ello.
  • depuración, paso a paso, puntos de quiebre y relojes
  • refactorización para obtener una mejor comprensión
  • mirando fijamente el código
  • mira el volcado de memoria / núcleo
  • alimentándolo con diferentes datos
  • mostrándolo a otras personas
  • cambiar a un idioma sin punteros (y un nuevo conjunto de problemas) ...

En un nivel más abstracto, tiene tres enfoques: 1. trabajar con el código 2. mirar el programa mientras se ejecuta 3. mirar los resultados después de que hizo algo estúpido

por cierto, un error de puntero no tiene que crear un segfault.

Como programador de Amiga, usé casi todo. Y sí se reinicia donde la práctica común.

openCage
fuente
4

En el IBM 360, ejecutando trabajos por lotes Fortran, solíamos obtener volcados de núcleo hexadecimal. Tal volcado podría tener hasta una pulgada de grosor de papel de impresora verde y blanco doblado en abanico. Deciría cuáles eran los registros, y desde allí podríamos dar marcha atrás y descubrir qué estaba haciendo el programa. Podríamos encontrar cada subrutina y averiguar dónde almacenaba su dirección de retorno, para poder ver el contexto. Sería útil tener una lista de ensambladores del programa.

Mike Dunlavey
fuente
2

Una vez que estaba trabajando en la corrección de errores en un famoso software de presentación de Windows 3.1.

Tenía un error que, cuando ocurrió, causó la pantalla azul de la muerte.

El error solo ocurrió cuando un cierto ciclo se había ejecutado más de 1000 veces. Utilicé las funciones avanzadas del depurador para dejar pasar un punto de interrupción 1000 veces y luego pasé cuidadosamente por el programa. Cada vez que fui demasiado lejos o salté una llamada de función que contenía el error Windows Blue Screened.

Finalmente, después de varios días de trabajo, lo reduje a una función que se estaba quedando sin memoria y, en lugar de mostrar un mensaje de error, agregué el mensaje de error a un búfer. Con cada iteración posterior, destruyó más memoria hasta que se sobrescribió algo crucial y Windows se destruyó.

La solución fue la depuración de las habilidades y la perseverancia.

Stuart Woodward
fuente