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;
}
Foi útil?

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top