Comment ont-ils débogué les erreurs de segmentation avant la mémoire protégée?

20

Maintenant, quand je fais une erreur de programmation avec des pointeurs en C, j'obtiens une belle erreur de segmentation, mon programme plante et le débogueur peut même me dire où ça s'est mal passé.

Comment ont-ils fait cela au moment où la protection de la mémoire n'était pas disponible? Je peux voir un programmeur DOS tripoter et planter tout le système d'exploitation lorsqu'il a fait une erreur. La virtualisation n'était pas disponible, il ne pouvait donc que redémarrer et réessayer. Est-ce que ça s'est vraiment passé comme ça?

Bart Friederichs
la source
4
Oui, c'est comme ça que ça s'est passé. Un redémarrage aléatoire de l'ordinateur s'est produit et s'est produit souvent. La protection de la mémoire est une chose merveilleuse :)
Rocklan
7
Lorsque vous n'avez pas de mémoire protégée, il n'y a pas de défaut de segmentation. Bien sûr, même si vous avez une mémoire protégée, vous pouvez toujours encombrer votre propre espace; l'OS s'en fiche.
Blrfl
3
Même maintenant, de nombreuses erreurs de pointeur ne provoquent pas une belle erreur de segmentation.
CodesInChaos
1
Au moment de DOS, la mémoire protégée existait déjà dans d'autres systèmes d'exploitation.
mouviciel

Réponses:

36

Je peux voir un programmeur DOS tripoter et planter tout le système d'exploitation lorsqu'il a fait une erreur.

Ouais, c'est à peu près ce qui s'est passé. Sur la plupart des systèmes dotés de cartes mémoire, l'emplacement 0 était marqué comme non valide, de sorte que les pointeurs nuls pouvaient être facilement détectés, car c'était le cas le plus courant. Mais il y a eu beaucoup d'autres cas, et ils ont causé des ravages.

Au risque de ressembler à un geezer, je dois souligner que l'accent actuel sur le débogage n'est pas la voie du passé. Beaucoup plus d'efforts ont été faits auparavant pour écrire des programmes corrects, plutôt que de supprimer des bogues de programmes incorrects. C'est en partie parce que c'était notre objectif, mais beaucoup parce que les outils ont rendu les choses difficiles. Essayez d'écrire vos programmes sur papier ou sur des cartes perforées, pas dans un IDE, et sans l'avantage d'un débogueur interactif. Cela vous donne le goût de l'exactitude.

Ross Patterson
la source
3
En fait, j'espérais que les "vieux geezers" répondraient à ma question. Rien ne vaut l'expérience de première main. Merci.
Bart Friederichs
6
Essayez d'écrire du code lorsque le matériel est disponible pour le débogage tous les soirs de 02h00 à 06h00, en supposant bien sûr que votre collègue ne l'a pas réservé pour sa session de débogage.
MSalters
@MSalters Effectivement! Lors de mon premier emploi, nous pourrions également réserver des créneaux le dimanche de 0700 à 1900 - un vrai régal, laissez-moi vous dire :-)
Ross Patterson
2
Je me souviens d'avoir écrit mon premier programme sur papier en rentrant de l'université. Le lendemain, quand j'ai pu le frapper et l'exécuter, c'était
parfait
1
@JanDoggen, pareil pour moi. Lorsque vous n'avez qu'un seul essai, vous faites que cet essai compte vraiment.
nalply
23

À l'époque, nous n'avions pas de protection de mémoire et toutes ces affaires délirantes! Nous avons utilisé printf pour déterminer où nous en étions dans le programme, et nous l'avons aimé !

Bien que sérieusement, cela signifiait généralement que nous étions juste plus prudents. Lorsque malloc est appelé, il devait y en avoir un autre ailleurs dans le programme, et une telle vérification était rigoureuse car en cas de problème, comme vous l'avez clairement souligné, les erreurs de segmentation ne sont pas des erreurs utiles.

Dans le cas de telles erreurs, le mieux que vous puissiez faire est d'essayer de comprendre quand de tels défauts de segmentation se produisent (à l'aide de printf) et, en regardant le code, de déterminer pourquoi l'accès à la mémoire à ce moment-là n'était pas valide et de revenir en arrière à partir de là.

En substance, la même chose se produit aujourd'hui, sauf que nous utilisons des débogueurs pour déterminer quand des erreurs se produisent, mais vous devez toujours comprendre pourquoi cela s'est produit, et ce n'est pas toujours aussi simple que de trouver la ligne dans laquelle l'erreur s'est produite. Les erreurs provoquent des erreurs comme une réaction en chaîne, et si vous étiez programmeur C à cette époque, vous passiez 20% de votre temps à coder et le reste du temps à vous arracher les cheveux pour corriger les bugs.

Neil
la source
2
Libérez les Mallocs!
Chris
1
De temps en temps, même aujourd'hui, même la pile d'appels et l'état variable sont totalement inutiles pour déterminer ce qui s'est mal passé et comment y remédier. C'est le cas en particulier si vous avez un logiciel complexe avec un grand nombre d'états possibles, dont certains interdépendants et d'autres mutuellement exclusifs. Une seule écriture parasite n'importe où et une assertion omise pour la condition préalable garantie peuvent vous amener là.
un CVn le
1
@ MichaelKjörling, je pense que pour ce qui concerne la découverte d'erreurs dans les programmes, nous n'avons progressé que pour ce qui concerne la recherche du déclencheur d'erreur, mais nous avons encore des kilomètres à parcourir pour découvrir la cause de ces erreurs. Les affirmations aident à me garder sain d'esprit, c'est sûr. :)
Neil
6

bien ..

une erreur de segmentation est un très bon indicateur que quelque chose ne va pas, mais vous devez toujours trouver la cause première. Donc, si vous posez la question comment trouvez-vous la cause première que la réponse n'est pas très différente aujourd'hui qu'elle ne l'était alors. Bien sûr, les langues et les outils sont devenus plus faciles à utiliser, mais le taktik général est le même:

  • la journalisation permet de trouver la zone où se situe votre problème. La recherche binaire printf en est une forme.
  • débogage, étape par étape, points d'arrêt et montres
  • refactoring pour mieux comprendre
  • regarder fixement le code
  • regardez le vidage mémoire / core
  • le nourrir avec des données différentes
  • le montrer à d'autres personnes
  • passer à une langue sans pointeurs (et un nouvel ensemble de problèmes) ...

À un niveau plus abstrait, vous avez trois approches: 1. travailler avec le code 2. regarder le programme en cours d'exécution 3. regarder les résultats après avoir fait quelque chose de stupide

btw une erreur de pointeur n'a pas à créer un défaut de segmentation.

En tant que programmeur Amiga, j'ai utilisé presque tout cela. Et oui redémarre là où la pratique courante.

openCage
la source
4

Sur l'IBM 360, exécutant des travaux par lots Fortran, nous obtenions des vidages de mémoire hexadécimaux. Un tel vidage peut atteindre jusqu'à un pouce d'épaisseur de papier pour imprimante vert et blanc plié en éventail. Cela indiquerait quels étaient les registres et, à partir de là, nous pourrions revenir en arrière et comprendre ce que faisait le programme. Nous pourrions trouver chaque sous-programme et déterminer où il a stocké son adresse de retour, afin que nous puissions voir le contexte. Il serait utile d'avoir une liste d'assembleurs du programme.

Mike Dunlavey
la source
2

Une fois, je travaillais sur la correction de bugs sur un logiciel de présentation Windows 3.1 alors célèbre.

J'ai eu un bug qui, lorsqu'il s'est produit, a provoqué l'écran bleu de la mort.

Le bogue ne s'est produit que lorsqu'une certaine boucle a été exécutée plus de 1000 fois. J'ai utilisé les fonctionnalités avancées du débogueur pour laisser passer un point d'arrêt 1000 fois, puis j'ai soigneusement parcouru le programme. Chaque fois que j'allais trop loin ou que je sautais un appel de fonction contenant le bogue Windows Blue Screened.

Enfin, après plusieurs jours de travail, je l'ai réduit à une fonction qui manquait de mémoire et au lieu d'afficher un message d'erreur, j'ai ajouté le message d'erreur à un tampon. À chaque itération suivante, il a supprimé plus de mémoire jusqu'à ce que quelque chose de crucial soit remplacé et que Windows soit supprimé.

Déboguer les compétences et la persévérance était la solution.

Stuart Woodward
la source