Mencionei "buffer overflows" em um comentário à resposta de Pythagras, provavelmente devo esclarecer um pouco o que eu quis dizer. Em C, não basta saber que trabalhar diretamente com a memória é perigoso - você também deve entender as maneiras precisas de como é perigoso. Eu realmente não gosto da metáfora de "dar um tiro no pé" para todos esses casos - na maioria das vezes, não é você que puxa o gatilho, mas muitas vezes é um ator com interesses contrários aos seus e / ou dos de seus usuários. .
Por exemplo, em uma arquitetura com uma pilha descendente (as arquiteturas mais populares se encaixam nessa conta - x86 e ARM geralmente incluídos), quando você chama uma função, o endereço de retorno da função será colocado na pilha após as variáveis locais definidas no corpo da função. Portanto, se você declarar um buffer como variável local e expor essa variável ao mundo externo sem verificar o estouro de buffer, assim:
void myFn(void) {
char buf[256];
gets(buf);
}
um usuário externo pode enviar uma string que sobrescreve o endereço de retorno da pilha - basicamente, ele pode alterar a idéia de tempo de execução do programa do gráfico de chamada que leva à função atual. Portanto, o usuário fornece uma string que é a representação binária de algum código executável para sua arquitetura, preenchimento suficiente para sobrecarregar a pilha myFn
e alguns dados adicionais para substituir o endereço de retorno myFn
e apontar para o código que ele forneceu. Se isso acontecer, quando myFn
normalmente retornaria o controle ao chamador, ele passaria a codificar o código fornecido pelo usuário mal-intencionado. Se você escrever código C (ou C ++) com potencial de exposição a usuários não confiáveis, precisará entender esse vetor de ataque. Você deve entender por que um estouro de buffer na pilha é frequentemente (mas nem sempre) mais facilmente explorável do que um no heap, e deve entender como a memória no heap é organizada (não em muitos detalhes, necessariamente, mas o A idéia de que uma malloc()
região possui estruturas de controle ao seu redor pode ajudar a entender por que seu programa trava em outra malloc()
ou em free()
).
C expõe você a detalhes de baixo nível sobre como sua máquina funciona e fornece a você um controle mais direto sobre sua máquina do que qualquer outro idioma editado pelo usuário hoje em dia. Com grande poder, vem uma grande responsabilidade - você realmente precisa entender esses detalhes de baixo nível para trabalhar com C com segurança e eficácia.