Em 1989, Felix Lee, John Hayes e Angela Thomas escreveram o teste de Hacker sob a forma de um questionário com muitas piadas internas, como “ Você come bolor de lodo? "
Estou considerando a seguinte série:
0015 Ever change the value of 4?
0016 ... Unintentionally?
0017 ... In a language other than Fortran?
Existe uma anedota específica tornando o número "4" particular na série?
Alguma implementação do Fortran permitiu modificar o valor das constantes? Isso foi possível em outros idiomas de uso comum na época?
4
para5
nas listas de números inteiros internados.4 = 5
foi possível.Respostas:
Antigamente (anos 70 e anteriores), alguns computadores não tinham MMU (e isso é verdade hoje para microcontroladores muito baratos).
Nesses sistemas, não há proteção de memória e, portanto, nenhum segmento somente leitura no espaço de endereço , e um programa com erros pode sobrescrever uma constante (na memória de dados ou mesmo dentro do código da máquina).
Os compiladores Fortran na época passaram argumentos formais por referência . Portanto, se você fez
CALL FUN(4)
e oSUBROUTINE FUN(I)
corpo dela está mudandoI
- por exemplo, com uma declaraçãoI = I + 1
no corpo, você pode sofrer um desastre, alterando 4 para 5 no chamador (ou pior).Isso também aconteceu nos primeiros microcomputadores, como o IBM PC AT original de 1984, com o MS-DOS
FWIW, eu tenho idade suficiente para ter usado, como adolescente no início dos anos 1970, esses computadores: IBM1620 e CAB500 (em um museu: esses são computadores da década de 1960!). O IBM1620 foi bastante divertido: usado em tabelas de memória para adições e multiplicações (e se você sobrescreveu essas tabelas, o caos se seguiu). Portanto, não apenas você pode sobrescrever um 4, mas também pode sobrescrever todas as adições futuras de 2 + 2 ou multiplicações 7 * 8 (mas eu realmente esqueci esses detalhes sujos para que pudesse estar errado).
Hoje, você pode sobrescrever o código do BIOS na memória flash, se estiver perseverante o suficiente. Infelizmente, não me sinto mais tão divertido, então nunca tentei. (Tenho até medo de instalar alguns LinuxBios na minha placa-mãe).
Nos computadores e sistemas operacionais atuais, passar uma constante por referência e alterá-la dentro do receptor apenas provocará uma violação de segmentação , que parece familiar para muitos desenvolvedores de C ou C ++.
BTW: nitpicking: overwriting 4 não é uma questão de linguagem, mas de implementação.
fonte
gfortran
. As constantes são colocadas em seu segmento e transmitidas por referência a uma sub-rotina. Por padrão, a seção constante é somente leitura, portanto, o erro de proteção de memória mata o programa.Foi um efeito colateral não intencional da estratégia de avaliação de chamadas de funções do FORTRAN em combinação com uma otimização de compilador incorreta.
O FORTRAN II introduziu funções e sub-rotinas definidas pelo usuário com seus argumentos passados por referência . (Ora, eu não sei. Provavelmente era mais eficiente do que o valor de passagem no hardware IBM da época.)
Normalmente, passagem por referência significa que você precisa passar um valor l (como uma variável) em vez de um valor r. Mas os designers do FORTRAN decidiram ser úteis e permitir que você transmita valores-r como argumentos de qualquer maneira. O compilador geraria automaticamente uma variável para você. Então, se você escreveu:
o compilador converteria isso nos bastidores para algo como
Também havia uma otimização de compilador comum chamada “pool literal”, que consolidaria várias instâncias da mesma constante numérica na mesma variável gerada automaticamente. (Vários idiomas da família C exigem isso para literais de string.) Portanto, se você escreveu
isso seria tratado como se fosse
o que parece perfeitamente razoável até que você tenha um subprograma que altera o valor de seus parâmetros.
Estrondo!
CALL SUBBAR(4)
alterou o valor de 4 no pool literal para 5. E então você fica se perguntando por queSUBBAZ
está assumindo que você passou um 5 em vez do que4
você realmente escreveu no código.As versões mais recentes do Fortran atenuam esse problema, permitindo que você declare a
INTENT
variável comoIN
ou ouOUT
dando um erro (ou pelo menos um aviso) se você passar uma constante comoOUT
parâmetro.fonte
No FORTRAN, quando uma constante é passada para outro procedimento, ela não é mais protegida. É a isso que eles se referem. Outras linguagens de programação populares na mesma época foram C e Pascal, que não tinham (e ainda não têm) esse problema. Talvez existam linguagens de programação mais antigas que eu não conheço e que tenham o mesmo problema.
fonte
.rodata
segmento somente leitura (como fazem os compiladores atuais), não alterará a constante, mas causaria um SEGV.