Como eles depuraram falhas de segmentação antes da memória protegida?

20

Agora, quando cometo um erro de programação com ponteiros em C, recebo uma boa falha de segmentação, meu programa falha e o depurador pode até me dizer onde deu errado.

Como eles fizeram isso no momento em que a proteção de memória não estava disponível? Posso ver um programador do DOS mexendo e travando todo o sistema operacional quando cometeu um erro. A virtualização não estava disponível, então tudo o que ele pôde fazer foi reiniciar e tentar novamente. Realmente foi assim?

Bart Friederichs
fonte
4
Sim, foi assim que aconteceu. Uma reinicialização aleatória do computador aconteceu e aconteceu com frequência. Proteção de memória é uma coisa maravilhosa :)
Rocklan
7
Quando você não possui memória protegida, não existe uma falha de segmentação. Obviamente, mesmo se você tiver memória protegida, ainda poderá ganhar espaço no seu próprio espaço; o sistema operacional simplesmente não se importa com isso.
Blrfl
3
Mesmo agora, muitos erros de ponteiro não causam um bom segfault.
código é o seguinte
1
No momento do DOS, a memória protegida já existia em outros sistemas operacionais.
Mouviciel

Respostas:

36

Eu posso ver um programador do DOS mexendo e travando todo o sistema operacional quando ele cometeu um erro.

Sim, foi o que aconteceu. Na maioria dos sistemas que possuíam mapas de memória, o local 0 era marcado como inválido, para que indicadores nulos pudessem ser facilmente detectados, porque esse era o caso mais comum. Mas houve muitos outros casos, e eles causaram estragos.

Correndo o risco de parecer um velhote, devo salientar que o foco atual na depuração não é o caminho do passado. Muito mais esforço foi feito anteriormente para escrever programas corretos, em vez de remover erros de programas incorretos. Parte disso foi porque esse era o nosso objetivo, mas muito foi porque as ferramentas dificultaram as coisas. Tente escrever seus programas em papel ou em cartões perfurados, não em um IDE e sem o benefício de um depurador interativo. Dá a você um gosto pela correção.

Ross Patterson
fonte
3
Na verdade, eu esperava que "velhotes" respondessem à minha pergunta. Nada supera a experiência em primeira mão. Obrigado.
Bart Friederichs
6
Tente escrever o código quando o hardware estiver disponível para depuração todas as noites, das 02:00 às 06:00, assumindo, é claro, que seu colega não o reservou para a sessão de depuração.
precisa saber é o seguinte
@MSalters Indeed! No meu primeiro emprego, também pode reservar ranhuras no domingo 0.700-1.900 - um verdadeiro deleite, me deixe te dizer :-)
Ross Patterson
2
Lembro-me de escrever meu primeiro programa em papel, voltando da universidade para casa. No dia seguinte, quando eu poderia perfurar-lo e executá-lo, ele foi impecável ;-)
Jan Doggen
1
@JanDoggen, o mesmo para mim. Quando você tem apenas uma tentativa, você faz com que ela realmente conte.
nalply
23

Na minha época, não tínhamos proteção de memória e todos aqueles negócios esquisitos! Usamos o printf para determinar onde estávamos no programa e gostamos !

Embora com toda a seriedade, geralmente significava que éramos mais cuidadosos. Onde o malloc é chamado, era necessário haver um local gratuito em algum outro lugar do programa, e essa verificação era rigorosa porque, no caso de um problema, como você claramente apontou, as falhas de segmentação não são erros úteis.

No caso de tais erros, o melhor que você pode fazer é tentar entender quando essas falhas de segmentação ocorrem (usando printf) e, observando o código, determinar por que o acesso à memória naquele momento não era válido e trabalhar a partir daí.

Essencialmente, o mesmo acontece hoje, exceto que usamos depuradores para determinar quando os erros ocorrem, mas você ainda precisa entender por que isso aconteceu, e nem sempre é tão simples quanto encontrar a linha na qual o erro ocorreu. Erros causam erros como uma reação em cadeia e, se você fosse um programador C naquela época, passava 20% do seu tempo codificando e o restante do tempo arrancando os cabelos para corrigir bugs.

Neil
fonte
2
Liberte os Mallocs!
31413 Chris
1
De vez em quando, até hoje, até a pilha de chamadas e o estado variável são totalmente inúteis para determinar exatamente o que diabos deu errado e como corrigi-lo. Esse é o caso particularmente se você tiver um software complexo com um grande número de estados possíveis, alguns dos quais interdependentes e outros mutuamente exclusivos. Uma única gravação dispersa em qualquer lugar e uma afirmação omitida para a pré-condição garantida podem levá-lo para lá.
um CVn
1
@ MichaelKjörling, acho que, no que diz respeito à descoberta de erros nos programas, progredimos apenas no que diz respeito à localização do gatilho do erro, mas ainda temos muitas milhas para descobrir a causa desses erros. As afirmações ajudam a me manter sã, com certeza. :)
Neil
6

bem ..

um segfault é um indicador muito bom de que algo está errado, mas você ainda precisa encontrar a causa raiz. Portanto, se você fizer a pergunta: como você encontra a causa raiz, a resposta não é muito diferente hoje do que era então? É claro que as linguagens e ferramentas se tornaram mais fáceis de trabalhar, mas o taktik geral é o mesmo:

  • o registro ajuda a encontrar a área onde está o seu problema. Pesquisa binária printf é uma forma disso.
  • depuração, passo a passo, pontos de interrupção e relógios
  • refatoração para obter uma melhor compreensão
  • olhando fixamente para o código
  • veja o despejo de memória / núcleo
  • alimentando-o com dados diferentes
  • mostrando para outras pessoas
  • mudar para um idioma sem ponteiros (e um novo conjunto de problemas) ...

Em um nível mais abstrato, você tem três abordagens: 1. trabalhe com o código 2. analise o programa enquanto ele é executado 3. analise os resultados depois de fazer algo estúpido

Entre um erro de ponteiro não é necessário criar um segfault.

Como programador do Amiga, usei praticamente tudo isso. E sim reinicia onde prática comum.

openCage
fonte
4

No IBM 360, executando tarefas em lote do Fortran, costumávamos obter dumps hexadecimais. Esse depósito poderia ter até uma polegada de espessura de papel de impressora verde e branco dobrado em leque. Contaria quais eram os registros e, a partir daí, poderíamos voltar atrás e descobrir o que o programa estava fazendo. Poderíamos encontrar cada sub-rotina e descobrir onde ele armazenava seu endereço de retorno, para que pudéssemos ver o contexto. Seria bom ter uma lista de montadores do programa.

Mike Dunlavey
fonte
2

Uma vez eu estava trabalhando na correção de bugs em um famoso software Windows 3.1 Presentation.

Eu tinha um bug que, quando ocorreu, causou a Tela Azul da Morte.

O bug ocorreu apenas quando um determinado loop foi executado mais de 1000 vezes. Usei os recursos avançados do depurador para permitir que um ponto de interrupção passasse 1000 vezes e, em seguida, passei cuidadosamente pelo programa. Toda vez que eu fui longe demais ou pulei uma chamada de função que continha o bug Windows Blue Screened.

Finalmente, após vários dias de trabalho, reduzi-o a uma função que estava ficando sem memória e, em vez de exibir uma mensagem de erro, anexei a mensagem de erro a um buffer. A cada iteração subseqüente, ele armazenava mais memória na memória até que algo crucial fosse substituído e o Windows, na lixeira.

Habilidades de depuração e perseverança foram a solução.

Stuart Woodward
fonte