Linux elimina a API `strncpy` após seis anos de trabalho, 360 patches

Strings Terminadas em NUL vs Prefixadas por Comprimento / Tipos de String “Reais”

  • Muitos argumentam que as strings C terminadas em NUL são uma das piores escolhas de design da computação: fáceis de transbordar, difíceis de raciocinar e armadilhas de desempenho (por exemplo, chamadas repetidas a strlen transformando O(N) em O(N²)).
  • Outros observam que elas foram um compromisso pragmático em máquinas minúsculas dos anos 1970; sequências terminadas por sentinela (strings, arrays de ponteiros, listas encadeadas) eram baratas e combinavam com a prática em assembly.
  • Strings no estilo Pascal ou prefixadas por comprimento evitam bugs de terminador ausente, mas trazem problemas: campos de comprimento de tamanho fixo (historicamente 255 caracteres), confusão entre bytes/codepoints/grafemas e dificuldade para fazer substrings sem copiar, a menos que você vá para “fat pointers” (ponteiro+comprimento).
  • Variantes modernas discutidas: struct { size_t length; T* ptr; } de D, BSTRs e cabeçalhos de Pascal/Delphi/Free Pascal, codificações dinâmicas/variáveis de comprimento, e tipos “span”/slice. Trade-offs: sobrecarga de memória vs velocidade vs slicing sem cópia.

NULL, NUL e Tipos Option

  • A discussão distingue repetidamente NUL (byte terminador 0) de NULL (ponteiro inválido).
  • Alguns veem NULL como algo aceitável e necessário; o problema real é não conseguir declarar ponteiros não nulos.
  • Outros enfatizam os modernos tipos “option”/soma (por exemplo, Option<T>) como a forma correta de representar valores “não definidos”, impostos pelo sistema de tipos em tempo de compilação.
  • Há debate sobre se ambientes de baixo nível podem ou devem substituir NULL por tais construções, ou usá-las como uma abstração de nível mais alto que se compila para representações com possibilidade de null.

Contexto Histórico e de Padrões

  • Vários comentários destacam as origens do C: RAM minúscula (dezenas de KiB), compiladores de passagem única, limites de endereçamento do PDP-11 e reutilização de idioms já existentes. Nesse contexto, strings terminadas em null e o decay de ponteiro/array eram vistos como compromissos inteligentes, não erros.
  • Propostas posteriores como fat pointers/slices e APIs mais seguras (por exemplo, strlcpy) são citadas como oportunidades perdidas; criticam-se comitês por adicionar recursos complexos (VLAs, _Generic) enquanto mantiveram o modelo central de strings do C e a stdlib praticamente congelados.

strncpy, APIs do Kernel e Segurança

  • strncpy é descrita como amplamente mal utilizada e contraintuitiva: ela preenche com zeros, pode não terminar com NUL ao truncar e foi concebida originalmente para campos de tamanho fixo e preenchidos (por exemplo, antigas entradas de diretório), não como um “strcpy seguro”.
  • As funções substitutas do kernel (strscpy, strscpy_pad, strtomem_pad, memcpy_and_pad, memcpy) codificam uma intenção mais clara (terminada ou não terminada, preenchimento vs cópia bruta), ao custo de mais APIs, mas com melhor segurança e sinalização de desempenho.
  • Alguns consideram essa proliferação “complicada”; outros argumentam que uma única ferramenta “canivete suíço” seria mais lenta e obscureceria a intenção.

IA e Refatoração Automatizada

  • Uma linha de discussão pergunta se codificadores baseados em LLM poderiam ter automatizado a maior parte do trabalho de remoção de strncpy.
  • Defensores relatam boas experiências usando LLMs para refatorar muitos programas em C e argumentam que seis anos é tempo demais para mudanças essencialmente mecânicas.
  • Céticos respondem que, em um projeto do porte do kernel, os principais gargalos são revisão, coordenação e testes, não apenas edição; comportamentos sutis a jusante e a dependência de semânticas antigas precisam ser cuidadosamente auditados.
  • Há uma fadiga visível com a IA sendo inserida em toda discussão de programação, junto com curiosidade sobre seu potencial para refatorações em grande escala.