Segmentation fault with recieved signal SIGSEGV

I'm working on an implementation of the tail Unix command, and this is my code so far:

#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;
}

The problem is that somewhere in the resize() function i get a Segmentation Fault, and when i ran the program in GDB, i got Program received signal SIGSEGV Segmentation fault. 0x00000000004006f7 in resize (). This tells me that I have some kind of memory allocation problem in resize(), but so far I have been unable to find the bug. What should I do?

Answers


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

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

You seem to expect, that in main() data will point to the memory allocated in tailRead(). That is not the case. In tailRead() data is a copy of the pointer data from main() you only change the copy, not the original pointer. The original pointer still points to 0.

Then you call resize() with a null pointer, which of course will lead to a segmentation violation.

Solution

use a pointer to a pointer instead, to modify the original pointer.

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);
     /* ... */
}

You have the same issue with stdIn(). It changes data without reflecting the change to the data-pointer at the call site in tailRead(). You leave stdIn() leaking memory and continue to work with a dangling pointer.


I think your problem is here...

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

You are trying to access data[counter] when counter is greater than what you allocated for the previous malloc(). By this I mean, you are reading beyond the (current) legitimate end of data. Make sense?

EDIT: Now that I think about it, this may not cause the segfault, but it is a problem.


Need Your Help

Deploying Flask app on EC2 for localhost access

python apache amazon-ec2 flask

I have finished up a simple Flask app that I am trying to host on an AWS EC2 instance with Apache2. I've been following this tutorial.

How do I commit the restful_authentication plugin to my git repo?

ruby-on-rails git

How do I add a the http://github.com/technoweenie/restful-authentication/tree/master plugin to my Rails project and the commit it to the git repo ? I need it to be committed with the project.