2015-12-01 7 views
1

Я работаю над реализацией команды tail Unix, и это мой код до сих пор:вина Сегментация с SIGSEGV за полученный сигнал

#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <errno.h> 
#include <stdlib.h> 

char *resize(char *data, int size) 
{ 
    char *newData = (char*) malloc((size + 1) * sizeof(char)); 
    int counter; 

    for(counter = 0; counter < size; counter++) 
     newData[counter] = data[counter]; 
    free(data); 
    return newData; 
} 

int printLines(char *data, int size) 
{ 
    int lines = 0, position, counter; 

    for(position = size - 1; position > -1; position--) 
    { 
     if (data[position] == '\n') lines++; 
     if (lines == 10) break; 
    } 

    if (lines == 10) 
     for(counter = position; counter < size; counter++) 
     { 
      write(STDOUT_FILENO, &data[counter], 1); 
     } 
    else write(STDOUT_FILENO, data, size); 
    return 0; 
} 

int stdIn(char *data, int size) 
{ 
    char buff, end = '\n'; 
    int rState = 0; 

    while ((rState = read(STDIN_FILENO, &buff, 1)) > 0) 
    { 
     if(rState < 0) 
     { 
      if(errno == EINTR) rState = 0; 
      else 
      { 
       perror("read()"); 
       return 1; 
      } 
     } 
     data = resize(data, size); 
     data[size - 1] = buff; 
     size++; 
    } 

    if(rState == 0) write(STDOUT_FILENO, &end, 1); 
    return 0; 
} 

int tailRead(char *data, char *fileName) 
{ 
    int size = 1; 
    data = (char*)malloc(size * sizeof(char)); 

    if(fileName == 0 || fileName == "-") 
    { 
     if(stdIn(data, size) > 0) return 1; 
    } 
    else 
    { 

    } 

    printLines(data, size); 
    return 0; 
} 


int main(int argc, char *argv[]) 
{ 
    char *data = 0; 
    int counter; 

    if(argc == 1) 
    { 
     tailRead(data, 0); 
     if(data > 0) return 1; 
    } 
    else for (counter = 1; counter < argc; counter++) 
    { 
     tailRead(data, argv[counter]); 
     if(data > 0) return 1; 
    } 

    return 0; 
} 

Проблема заключается в том, что где-то в функции resize() я получаю Segmentation Ошибка, и когда я запускал программу в GDB, я получил Program received signal SIGSEGV Segmentation fault. 0x00000000004006f7 in resize(). Это говорит мне, что у меня есть проблема с распределением памяти в resize(), но до сих пор мне не удалось найти ошибку. Что мне делать?

+3

'resize (data, size);' -> 'data = resize (data, size);' – BLUEPIXY

+2

OT: Также вам может понравиться функция 'realloc()'. – alk

+0

Это была ошибка копирования-вставки, ошибка все еще там – Reaper9806

ответ

0
int tailRead(char *data, char *fileName) 
/* ... */ 

int main(int argc, char *argv[]) 
{ 
    char *data = 0; 
    /* ... */ 
     tailRead(data, 0); 
} 

Вы, кажется, ожидать, что в main()data будет указывать на память, выделенную в tailRead(). Это не относится к делу. В tailRead()data - это копия указателя data от main(), вы меняете копию, а не исходный указатель. Исходный указатель по-прежнему указывает на 0.

Затем вы вызываете resize() с нулевым указателем, что, конечно же, приведет к нарушению сегментации.

Решение

использовать указатель на указатель вместо того, чтобы изменить исходный указатель.

int tailRead(char **data, char *fileName) 
{ 
    int size = 1; 
    *data = (char*)malloc(size * sizeof(char)); 

    /* ... */ 
} 


int main(int argc, char *argv[]) 
{ 
    char *data = 0; 
    /* ... */ 
     tailRead(&data, 0); 
    /* ... */ 
} 

У вас такая же проблема с stdIn(). Он изменяет data, не задумываясь над изменением на data -поинтер на сайте звонка в tailRead(). Вы оставляете stdIn() утечкой памяти и продолжаете работать с висящим указателем.

+0

на самом деле 'chat *' в 'main()' не будет служить какой-либо цели, я использовал его только как отправную точку в начале, я собираюсь изменить 'tailRead()' чтобы не требовать аргумента thr 'char * data', поскольку он используется только в указанных выше функциях, а после' printLines() 'он служит для других целей. – Reaper9806

+0

@ Reaper9806 У вас такая же проблема с 'stdIn()'. Вы меняете указатель внутри с помощью 'data = resize (data, size)'. Это не будет отражено на стороне вызова в 'tailRead()'. 'printLines' будет вызываться с указателем на освобожденную память. BTW: Есть ли веская причина не использовать 'realloc()' вместо 'resize()'? В случае, если макет памяти позволяет это, 'realloc()' избежит копирования и просто изменит размер выделенного фрагмента памяти. – cdonat

-1

Я думаю, ваша проблема здесь ...

for(counter = 0; counter < size; counter++) 
     newData[counter] = data[counter]; 

Вы пытаетесь получить доступ к data[counter], когда счетчик больше, чем то, что вы выделили для предыдущего malloc(). Под этим я подразумеваю, что вы читаете за пределами (текущего) законного конца data. Имеют смысл?

EDIT: Теперь, когда я думаю об этом, это может не вызвать segfault, но это проблема.

+0

Я тестировал его несколько раз, это никогда не было проблемой. – Reaper9806

+0

Я согласен, это, вероятно, не вызвало ваш segfault, но вы обращаетесь и копируете неинициализированный байт данных. Вы должны использовать 'for (counter = 0; counter pedwards