带有接收信号SIGSEGV的分段故障

时间:2015-12-01 16:52:41

标签: c memory segmentation-fault gdb tail

我正在研究tail Unix命令的实现,到目前为止这是我的代码:

#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()函数中的某个地方出现了分段错误,当我在GDB中运行程序时,我得到了Program received signal SIGSEGV Segmentation fault. 0x00000000004006f7 in resize ()。这告诉我resize()中存在某种内存分配问题,但到目前为止我一直无法找到该错误。我该怎么办?

2 个答案:

答案 0 :(得分: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()内存泄漏并继续使用悬空指针。

答案 1 :(得分:-1)

我认为你的问题就在这里......

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

当计数器大于您为之前data[counter]分配的值时,您正尝试访问malloc()。我的意思是,你正在超越data的(当前)合法结束。有意义吗?

编辑:现在我考虑一下,这可能不会导致段错误,但这是一个问题。