【问题标题】:Segmentation fault with recieved signal SIGSEGV收到信号 SIGSEGV 的分段错误
【发布时间】:2015-12-01 16:52:41
【问题描述】:

我正在实现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() 中存在某种内存分配问题,但到目前为止我一直无法找到该错误。我该怎么办?

【问题讨论】:

  • resize(data, size); --> data=resize(data, size);
  • OT:你也可以看看realloc()函数。
  • 这是一个复制粘贴错误,错误仍然存​​在
  • 您的 printLines 函数正在被释放的 data 指针调用。
  • 是的,我刚才注意到了,由于某种原因,在我刚刚编译后,Segmentation fault 就消失了。 printLines() 我可以修复。

标签: c memory segmentation-fault gdb tail


【解决方案1】:
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,但不会反映对tailRead() 调用站点上data 指针的更改。您离开 stdIn() 泄漏内存并继续使用悬空指针。

【讨论】:

  • 实际上,main() 中的chat * 并没有任何作用,我一开始只是将其用作一种起点,我将修改@ 987654339@ 函数不需要char *data 参数,因为它只在上面的函数中使用,在printLines() 之后它用于其他目的。
  • @Reaper9806 您对stdIn() 有同样的问题。你用data = resize(data, size) 改变里面的指针。这不会反映在tailRead() 的调用方。 printLines 将使用指向已释放内存的指针调用。顺便说一句:有充分的理由不使用realloc() 而不是resize()?如果内存布局允许,realloc() 将避免复制,而只是更改分配的内存块的大小。
【解决方案2】:

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

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

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

编辑:现在我想起来了,这可能不会导致段错误,但这是一个问题。

【讨论】:

  • 我已经测试了好几次,这从来都不是问题。
  • 我同意,它可能不会导致您的段错误,但您正在寻址和复制未初始化的数据字节。你应该使用for(counter = 0; counter &lt; size-1; counter++)
猜你喜欢
  • 1970-01-01
  • 2013-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多