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()
函数,使其不需要thrchar*data
参数,因为它只在上述函数中使用,并且在printLines()
之后用于其他目的。@Reaper9806您对stdIn()
也有同样的问题。您可以使用data=resize(数据,大小)
更改内部指针。这将不会在tailRead()
中的调用端反映出来<代码>打印行
将使用指向已释放内存的指针进行调用。顺便问一下:是否有充分的理由不使用realloc()
而不是resize()
?在内存布局允许的情况下,realloc()
将避免复制,只需更改分配内存块的大小。我已经对其进行了多次测试,这从来都不是问题。我同意,这可能不是导致SEGFULT的原因,但您正在寻址和复制未初始化的数据字节。您应该使用for(counter=0;counter