C 接收信号SIGSEGV的分段故障

C 接收信号SIGSEGV的分段故障,c,memory,segmentation-fault,gdb,tail,C,Memory,Segmentation Fault,Gdb,Tail,我正在研究tailUnix命令的实现,到目前为止,这是我的代码: #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 siz

我正在研究
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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
字符*调整大小(字符*数据,整数大小)
{
char*newData=(char*)malloc((大小+1)*sizeof(char));
整数计数器;
用于(计数器=0;计数器<大小;计数器++)
newData[计数器]=数据[计数器];
免费(数据);
返回新数据;
}
整数打印行(字符*数据,整数大小)
{
int lines=0,位置,计数器;
对于(位置=大小-1;位置>-1;位置--)
{
如果(数据[位置]='\n')行++;
如果(行==10)中断;
}
如果(行==10)
用于(计数器=位置;计数器<大小;计数器++)
{
写入(标准输出文件号和数据[计数器],1);
}
else写入(标准输出文件号、数据、大小);
返回0;
}
int stdIn(字符*数据,int大小)
{
字符buff,end='\n';
int rState=0;
而((rState=read(STDIN_FILENO,&buff,1))>0)
{
如果(rState<0)
{
如果(errno==EINTR)rState=0;
其他的
{
perror(“read()”);
返回1;
}
}
数据=调整大小(数据,大小);
数据[大小-1]=buff;
大小++;
}
如果(rState==0)写入(STDOUT_FILENO,&end,1);
返回0;
}
int tailRead(字符*数据,字符*文件名)
{
int size=1;
数据=(字符*)malloc(大小*大小(字符));
如果(文件名==0 | |文件名==“-”)
{
如果(stdIn(数据,大小)>0)返回1;
}
其他的
{
}
打印行(数据、大小);
返回0;
}
int main(int argc,char*argv[])
{
char*data=0;
整数计数器;
如果(argc==1)
{
尾读(数据,0);
如果(数据>0)返回1;
}
else(计数器=1;计数器0)返回1;
}
返回0;
}
问题是,
resize()
函数中的某个地方出现了分段错误,当我在GDB中运行该程序时,出现了
程序接收信号SIGSEGV分段错误。0x00000000004006f7在resize()
中。这说明我在
resize()
中遇到了某种内存分配问题,但到目前为止,我还无法找到该错误。我该怎么办

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

int main(int argc, char *argv[])
{
    char *data = 0;
    /* ... */
        tailRead(data, 0);
}
您似乎期望,
main()
中的数据将指向
tailRead()
中分配的内存。事实并非如此。在
tailRead()。原始指针仍然指向
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()
也有同样的问题。它更改
数据
,而不反映对
数据
指针的更改,指针位于
tailRead()
中的调用站点。您离开
stdIn()
泄漏内存,继续使用悬空指针工作。

我认为您的问题就在这里

    for(counter = 0; counter < size; counter++)
        newData[counter] = data[counter];
for(计数器=0;计数器
当计数器大于为上一个
malloc()
分配的值时,您正试图访问
data[counter]
。我的意思是,您的阅读超出了
数据的(当前)合法结尾。有道理吗


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

resize(数据,大小)-->
数据=调整大小(数据,大小)
OT:您可能还想看看
realloc()
函数。这是一个复制粘贴错误,错误仍然存在。您的
printLines
函数正在使用一个释放的
data
指针调用。是的,我刚才注意到了它,由于某种原因,在我刚刚编译它之后,分段错误就消失了。
printLines()
我可以修复。实际上,
main()
中的
chat*
没有任何用途,我只是在开始时将其用作一种起点,我将修改
tailRead()
函数,使其不需要thr
char*data
参数,因为它只在上述函数中使用,并且在
printLines()
之后用于其他目的。@Reaper9806您对
stdIn()
也有同样的问题。您可以使用
data=resize(数据,大小)
更改内部指针。这将不会在
tailRead()
中的调用端反映出来<代码>打印行
将使用指向已释放内存的指针进行调用。顺便问一下:是否有充分的理由不使用
realloc()
而不是
resize()
?在内存布局允许的情况下,
realloc()
将避免复制,只需更改分配内存块的大小。我已经对其进行了多次测试,这从来都不是问题。我同意,这可能不是导致SEGFULT的原因,但您正在寻址和复制未初始化的数据字节。您应该使用
for(counter=0;counter