Erro Malloc: soma de verificação incorreta para o objeto libertado
Pergunta
Eu estou trabalhando na implementação de cauda para uma atribuição. Eu tenho que trabalhar corretamente no entanto I parecem estar recebendo um erro do livre em momentos aleatórios.
Eu não posso ver, para segui-lo para baixo para um padrão ou qualquer coisa além disso é consistente.
Por exemplo, se eu ligar para o meu programa como "cauda -24 test.in" Gostaria de obter o o o erro de soma de verificação incorreta na mesma linha em várias execuções. No entanto, com diferentes arquivos e até mesmo diferentes números de linhas para imprimir voltar eu vou voltar sem erros.
Qualquer ideia sobre como rastrear o problema, eu venho tentando depurá-lo por horas sem sucesso.
Aqui está o código incorreto:
linhas é definido como um char ** e foi malloc como:
lines = (char**) malloc(nlines * sizeof(char *));
void insert_line(char *s, int len){
printf("\t\tLine Number: %d Putting a %d line into slot: %d\n",processed,len,slot);
if(processed > numlines -1){//clean up
free(*(lines+slot));
*(lines + slot) = NULL;
}
*(lines + slot) = (char *) malloc(len * sizeof(char));
if(*(lines + slot) == NULL) exit(EXIT_FAILURE);
strcpy(*(lines+slot),s);
slot = ++processed % numlines;
}
Solução
Sua rotina está escrevendo além do buffer de linha alocado.
O tamanho da linha passada como um argumento (ou seja, "len") que provavelmente não incluem o terminador NUL. Quando você chamar malloc para copiar a linha (ou seja, "s") você precisa alocar um byte extra para o terminator string:
*(lines + slot) = (char *) malloc((len + 1) * sizeof(char));
Outras dicas
Se você consistentemente pode reproduzir o problema com parâmetros de entrada específico, você deve depurar assim:
- Primeiro de depuração para a livre precisa que causa o problema.
- Em seguida, descobrir quando a memória que está prestes a ser free'd foi malloc'ed.
- Em seguida, depuração para o lugar onde a memória é malloc'ed.
- Localize na memória do espectador o bloco de memória alocado. Observe o início eo fim do bloco. Há provavelmente um valor especial chamado bloco guarda imediatamente antes e imediatamente após o bloco.
- Agora passo através do código até que a memória é free'd. Em algum momento o seu código deve erroneamente substituir o bloco de guarda. Esta é a declaração ofensiva.
Note que o problema poderia muito bem estar em uma parte completamente diferente do seu programa. Mesmo que seja este livre que está relatando o erro, o código que substitui o bloco de guarda pode estar em qualquer lugar.
A minha primeira pergunta é como você calcula len? É apenas strlen ou inclui espaço para o \ 0 terminator? Eu acho que você pode ser overshooting sua alocação em sua strcpy. Mau comportamento tenderá a acontecer nos limites das palavras e aparecem aleatoriamente. Além disso, certifique-se de que suas cordas de origem são um terminador nulo. Se você cometeu um erro no lado de leitura e não finalizá-las. Então strcpy pode estar substituindo aleatoriamente coisas.
*(lines + slot) = (char *) malloc(len * sizeof(char));
if(*(lines + slot) == NULL) exit(EXIT_FAILURE);
strcpy(*(lines+slot),s);
Talvez tente:
lines[slot] = (char *) malloc((len + 1) * sizeof(char));
if(lines[slot] == NULL) exit(EXIT_FAILURE);
if(strlen(s) <= len){
strcpy(lines[slot],s);
}
else{
/* do something else... */
}
Em termos de forma geral, eu também incentivá-lo a fazer algumas mudanças de estilo de fazer a coisa toda um pouco mais legível, mais fácil de seguir e resistente a erros.
Ponteiro aritmética é válido e divertido, mas eu acho que a sua intenção é um pouco mais claro se você usar a forma de matriz como:
free(lines[slot]);
lines[slot] = NULL;
em vez de
free(*(lines+slot));
*(lines + slot) = NULL;
Eu também incentivá-lo a usar menos estática. É fácil o suficiente para através deles, em uma estrutura de dados e passá-los ao redor em seus assessores e modificadores. Torna-se muito mais claro onde a ação está acontecendo o impede de fazer coisas como:
static int numlines = 0;
void insert_line(char *s, int len){
int numlines = 5;
onde você pode introduzir escopo questões que são apenas miserável para depuração.
Do NLINES e numLines têm o mesmo valor?
Será que o chamador de insert_line permitir espaço para o NUL arrastando ao passar o comprimento no segundo parâmetro?
Eu não tenho certeza que é relacionado, mas estas duas linhas parece suspeito para mim:
*(lines + slot) = (char *) malloc(len * sizeof(char));
if((lines + slot) == NULL) exit(EXIT_FAILURE);
Você primeiro atribuir o retorno de malloc para lines[slot]
e, em seguida, você verificar (lines+slot)
, se este for NULL, você tinha dereference um ponteiro NULL!
Além disso, se as linhas [entalhe] (a * (linhas + slot)) não é nulo, você vai vazar memória quando você vai atribuir o resultado de malloc () para ele.
Eu assumo lines
é um char
* linhas [] `e slot está dentro do! Limite permitido
Eu concordo com suspeita de remo sobre essas duas linhas, mas não a tangente que Remo saiu diante. Devemos compartilhar o crédito para encontrar este bug.
*(lines + slot) = some value
if((lines + slot) == NULL) then die
should be
if(*(lines + slot) == NULL) then die