Existem compiladores ou tempos de execução C esotéricos (estranhos), mas compatíveis com padrões?

6

Como sabemos, o padrão C não especifica muitos detalhes da implementação, por exemplo, valor do ponteiro NULL, ordem dos bits e bytes (endiannes), alinhamento nas estruturas e dos parâmetros da pilha, organização real da memória ( Eu não acho que o layout da pilha é necessário, apenas "auto"). Além disso, algumas outras partes são definidas (ou indefinidas) para produzir um comportamento indefinido, como desreferenciamento nulo (comumente segfault mas não necessariamente)

Como as plataformas modernas (ou é até o compilador?) (intencionalmente?) se comportam de maneira semelhante, é difícil confiar em algum comportamento consistente dos programas.

Então, existe uma variante unix ou uma plataforma inspirada no unix, (ou um compilador se for principalmente para o compilador?) que é padrão, mas intencionalmente estranho para produzir erros e apontar comportamentos indefinidos e não suportáveis? Existe uma coisa semelhante, mas para POSIX em vez de C? É mesmo uma coisa razoável tentar implementar?

    
por user62537 12.03.2014 / 12:18

3 respostas

6

O HP-UX da Hewlett Packard é o mais próximo que consigo pensar.

O compilador C permitirá a desreferência de ponteiro NULL, embora tenha havido um sinalizador para alterar isso. A pilha cresceu "para cima" (para endereços maiores) e a pilha cresceu (em direção a endereços menores) no hardware PA-RISC.

O hardware do PA-RISC também tinha algumas esquisitices além da inversão de pilha / pilha. Ele tinha um registrador de segmento (funcionava de maneira diferente dos segmentos x86), de modo que várias bibliotecas, na verdade, viviam em segmentos diferentes, e os ponteiros para funções não eram um único ponteiro de 64 bits. Não me lembro se o PA-RISC era tão rígido quanto o alinhamento do ponteiro, como o SPARC, no entanto.

Em um nível um pouco mais disponível, você pode usar compiladores C como Clang , Pcc ou mesmo Tcc , embora o Tcc tenha alguns problemas com os linkers e carregadores GNU devido a "símbolos fracos" como eu o entendo. No mínimo, você receberá mensagens de aviso diferentes desses compiladores alternativos, o que sempre vale a pena.

Você também pode tentar bibliotecas C alternativas, como Diet Libc ou Musl Eu tive código fazer coisas diferentes quando compilado contra Musl em oposição ao GNU Libc. Ambas as bibliotecas suportam links estáticos, o que o GNU Libc torna difícil ou impossível. O Musl ainda tem um sistema de vinculação dinâmica muito diferente, o que pode expor erros latentes no seu código.

    
por 12.03.2014 / 14:04
4

So, is there a unix variant or unix inspired platform, (or a compiler if it is mostly up to the compiler?) which is standard but intentionally weird to produce bugs and point out undefined behavior and unportability?

Não porque ...

Is it even a reasonable thing to try and implement?

... não se razoável significa "uma ferramenta que alguém razoavelmente deseja usar". Mas sim no sentido de que isso é o que um compilador C normal já está. Eles inevitavelmente permitem que você se envolva em comportamentos indefinidos de uma maneira definida (predicável). Por exemplo:

i = i++ + ++i;

É indefinido porque você modificou i várias vezes entre os pontos da sequência. No entanto, quase certamente um determinado compilador produzirá exatamente o mesmo resultado todas as vezes. Claro, isso não será documentado porque você não deve fazer isso em primeiro lugar, mas o compilador pode saber e pode lhe dizer se você perguntar.

Coloque isso em um arquivo e compile-o, gcc undefined.c . Sem problemas. Agora tente com alguns avisos habilitados, gcc -Wall -pendantic undefined.c :

undefined.c: In function ‘main’:
undefined.c:8:4: warning: operation on ‘i’ may be undefined [-Wsequence-point]
  i = i++ + ++i;
    ^

Lá vai você. Agora, tendo em mente que o compilador irá produzir o mesmo resultado aqui toda vez, você pode decidir explorar isso para qualquer propósito. Isso significa que é impossível para um compilador "intencionalmente ... produzir erros" quando você faz algo errado, se definirmos um "bug" como algo que você não queria que acontecesse. Não sabe o que você quer que aconteça e não pode. Portanto, não é possível produzir intencionalmente um resultado que você não pode prever.

Obviamente, pode "apontar um comportamento indefinido".

Se você quiser algo que possa ir além do erro do compilador, procure em valgrind . Existem outras coisas (possivelmente muito, muito caras) na mesma linha, mas esta é a única que usei.

Usar algo que você desenvolveu exclusivamente em uma máquina de 64 bits e compilá-lo e executá-lo em 32 bits também pode expor muitas facepalm - mas obviamente isso não é a maneira ideal de corrigir erros.

Finalmente: a maneira mais fácil de testar o software é testá-lo. Você escreve testes específicos enquanto trabalha, e os executa repetidas vezes: no final do dia, sempre que você adicionar uma nova peça, etc. Não há substituto para isso.

    
por 12.03.2014 / 15:27
2

O IBM Z Series roda o Linux, e isso é uma fera bastante estranha. Eu não sei se eles ainda usam EBCDIC.

Os Crays tinham todos tipos de dados de 32 bits (incluindo ´char´).

Existem compiladores C para algumas CPUs de 16 bits (lembro com carinho do Turbo C no PC, por exemplo). O tamanho da palavra é uma das diferenças que estão esperando para você ...

Em seu blog, John Regehr discute as ferramentas para verificar se os compiladores não fazem coisas boas. Ele tem vários posts sobre comportamento indefinido e como isso permite (algumas vezes surpreendentes) otimizações de código. Também discussões de comportamento indefinido "na natureza" ...

    
por 12.03.2014 / 15:26