проблема в освобождении памяти (или выделении) - PullRequest
0 голосов
/ 21 февраля 2019

Я получаю сообщение типа «free (): неверный указатель, прервано (сброшено ядро)», которое может указывать на выполняемую мной свободную операцию.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


char* ReadFile(char *filename)
{
char *buffer = NULL;
int string_size, read_size;
FILE *handler = fopen(filename, "r");

if (handler)
{
   // Seek the last byte of the file
    fseek(handler, 0, SEEK_END); 
 // Offset from the first to the last byte, or in other words,filesize
   string_size = ftell(handler);
   // go back to the start of the file
   rewind(handler);

   // Allocate a string that can hold it all
   buffer = (char*) malloc(sizeof(char) * (string_size + 1) );

   // Read it all in one operation
   read_size = fread(buffer, sizeof(char), string_size, handler);

   // fread doesn't set it so put a \0 in the last position
   // and buffer is now officially a string
   buffer[string_size] = '\0';

   if (string_size != read_size)
   {
       // Something went wrong, throw away the memory and set
       // the buffer to NULL
       free(buffer);
       buffer = NULL;
   }

    // Always remember to close the file.
    fclose(handler);
    return buffer;
 }

 return NULL;
 }
int newLineCounter(char *string)
{
if(string==NULL)
return -1;
int count=0;
for(int i=0;((string[i])!='\0');i++)
{
  if(string[i]=='\n')
  count++;
}
return count;
}

char ** arrayOfWords(char *str,int max)
{
  char **s;
  s=malloc(max*(sizeof(char *)+1));
  if(str==NULL||max<0)
  return NULL;
  int count=0;
  char *temp=strtok(str,"\n");
  int size=strlen(temp);
  s[0]=malloc((sizeof(char *)*(size+1)));
  s[0]=temp;
  // int count=0;
  while((s!=NULL)&&(count<max-1))
  {
   count++;
   char *temp=strtok(NULL,"\n");
   int size=strlen(temp);
   s[count]=malloc((sizeof(char *)*(size+1)));
   s[count]=temp;
  }
  count++;
  s[count]="\0";

  return s;
 }




int main()
{
    char *string = ReadFile("hi.txt");
    if(string==NULL) {
    printf("%s\n","Error,no files here" );
    }
  else {


int newLines=newLineCounter(string);
char **ret=arrayOfWords(string,newLines);
for(int i=0;i<newLines;i++)
{
printf("%s\n",ret[i] );
}
for(int i=0;i<newLines;i++)
{
free((ret[i]));
}

 free(ret);

 }
    return 0;
}

Итак, я выделяю память вмоя функция arrayOfWords для каждого «Слова», разделенного символом новой строки. После печати всех слов в моей основной функции я сначала пытаюсь освободить память, выделенную для каждого слова, а затем, надеюсь, освободить сам указатель. Когда я попыталсяОтладив это в GDB, я установил точку останова в цикле for, где я пытаюсь освободить каждую ссылку. Я получаю SIGABRT во время второй итерации, и я не понимаю, почему это происходит.Таким образом, ошибка возникает, когда я пытаюсь освободить содержимое в цикле for и задолго до освобождения фактического указателя.

Cheers.

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

У вас проблема с использованием malloc внутри функции char ** arrayOfWords(char *str,int max)

1> Для двойного указателя **s внутри функции char ** arrayOfWords(char *str,int max).

s=malloc(max*(sizeof(char *)+1));

должно быть

s=malloc(max*sizeof(char *));

, потому что s - это указатель на массив указателей на символы.

2> Для каждого элемента внутри **s.

s[0]=malloc((sizeof(char *)*(size+1)));
s[count]=malloc((sizeof(char *)*(size+1)));

они должны быть

s[0]=malloc((sizeof(char)*(size+1));
s[count]=malloc((sizeof(char)*(size+1)));

потому что s [i] теперь является указателем на массив символов.

0 голосов
/ 21 февраля 2019

Различные проблемы, но я думаю, что char *temp = strtok(NULL, "\n"); - главный виновник.

strtok(str, "\n"); сворачивание смежных "\n\n" в один токен, и позже for (int i = 0; i < newLines; i++) { free((ret[i])); } пытается освободить newLines линий, хотя только* Выделено count строк.

Код также может ошибочно пытаться освободить "\0"

Другие проблемы

Файл может не заканчиваться '\n' и т. Д. newLineCounter отключено на единицу.

Если файл содержит нулевой символ , newLineCounter() будет слишком маленьким.


Другие тудбиты

Проверьте возвращаемое значение из fseek(), ftell(), malloc()

Избегайте тихого усечения размера.ftell() возвращает long, strlen() возвращает size_t.


Некоторые не проверены альтернативный код:

Чтение файла

char *read_file(FILE *f, size_t *sz) {
  if (fseek(f, 0, SEEK_END)) return NULL;
  long len = ftell(handler);
  // If trouble finding the end or file too big ...
  if (len == -1 || (unsigned long) len >= SIZE_MAX) return NULL;

  *sz = len;
  rewind(handler);

  char *buffer = malloc(sizeof *buffer * (*sz + 1));
  size_t read_size = fread(buffer, sizeof *buffer, *sz, f);

  // Reading less than expected is not certainly wrong as the 
  // ftell technique is not _the_ best way to find file size,
  // It may overstate.
  // More robust code would use another approach.

  buffer[read_size] = '\0'; 
  *sz = read_size;
  return buffer;
}

Подсчет строк

size_t newLineCounter(const char *mem, size_t sz) { 
  size_t count=0;
  for(size_t i=0; i < sz; i++) {
    count += mem[i] == '\n';
  }
  if (i > 0 && mem[sz-1] != '\n') count++;
  return count;
}

Массив линий

char **arrayOfLines(char *str, size_t sz, size_t line_count) {
  char **lines = malloc(sizeof *lines * (line_count + 1));
  if (lines == NULL) return NULL;

  for(size_t i=0; i < line_count; i++) {
    const char *eol = memchr(str, '\n', sz);
    size_t len;
    if (eol == NULL) {
      len = sz;
    } else {
      len = (size_t)(eol - str + 1);
    }
    lines[i] = malloc(len + 1);
    if (lines[i]) {
      memcpy(lines[i], str, len);
      lines[i][len] = '\0';
    }
    str += len;
    sz -= len;
  }
  lines[line_count] = NULL;
  return lines;
}
...