C sprintf()期间的Segfault
因此,我目前正在为我的Unix操作系统类进行系统编程。这个程序所要做的就是读取一个二进制文件并将这些行输出到一个CSV文件中。我觉得我差不多完成了,但由于某种原因,我总是犯错误 澄清: fd1=输入文件, fd2=输出文件, numrecs=输入文件中的记录数。 在main()的某个地方:C sprintf()期间的Segfault,c,systems-programming,C,Systems Programming,因此,我目前正在为我的Unix操作系统类进行系统编程。这个程序所要做的就是读取一个二进制文件并将这些行输出到一个CSV文件中。我觉得我差不多完成了,但由于某种原因,我总是犯错误 澄清: fd1=输入文件, fd2=输出文件, numrecs=输入文件中的记录数。 在main()的某个地方: for(i=0;iid,recs->lname,recs->fname,recs->gpa,recs->iq); printf(“%s\n”,缓冲区); 写入(fd2,缓冲区,sizeof(缓冲区)); 返回
for(i=0;iid,recs->lname,recs->fname,recs->gpa,recs->iq);
printf(“%s\n”,缓冲区);
写入(fd2,缓冲区,sizeof(缓冲区));
返回0;
}
segfault发生在“sprintf(buffer等);”行上,但是,我不明白为什么会发生这种情况
这是gdb吐出的错误:
程序接收信号SIGSEGV,分段故障。0x0000000100000c87位于bin2csv处的bin2csv中(fd1=3,fd2=4)。c:25
25 sprintf(缓冲区,“%d,%s,%s,%f,%d\n”,记录->标识,记录->名称,
recs->fname,recs->gpa,recs->iq)
希望这是足够的信息。谢谢 它看起来像是一个指针。您正在将字节直接读取到该指针中,就像从文件中读取原始内存地址一样:
read(fd1, &recs, sizeof(recs))
然后在调用sprintf
时开始使用它。。。轰
实际上根本没有理由使用它(它是全球性的吗?)。。。即使您通过rec=&rec
初始化了它,并且假设您没有将其丢弃,它仍然不会包含该函数之外的有效地址。这是因为rec
是一个局部变量
因此,只需像这样直接阅读rec
:
read(fd1, &rec, sizeof(rec))
sprintf(buffer, 100, "%d, %s, %s, %f, %d\n", recs->id, recs->lname, recs->fname, recs->gpa, recs->iq);
然后在
sprintf
行上,使用rec.id
而不是recs->id
(等)。看起来recs
是一个指针。您正在将字节直接读取到该指针中,就像从文件中读取原始内存地址一样:
read(fd1, &recs, sizeof(recs))
然后在调用sprintf
时开始使用它。。。轰
实际上根本没有理由使用它(它是全球性的吗?)。。。即使您通过rec=&rec
初始化了它,并且假设您没有将其丢弃,它仍然不会包含该函数之外的有效地址。这是因为rec
是一个局部变量
因此,只需像这样直接阅读rec
:
read(fd1, &rec, sizeof(rec))
sprintf(buffer, 100, "%d, %s, %s, %f, %d\n", recs->id, recs->lname, recs->fname, recs->gpa, recs->iq);
然后在
sprintf
行中,使用rec.id
而不是recs->id
(等)。我在这里看到一些问题:
sprintf
不阻止写入字符串缓冲区的末尾。事实上,它不知道缓冲区的长度(在您的例子中是100字节)。由于您已经在堆栈中设置了缓冲区,如果sprintf
过度运行缓冲区(它可以使用长名字或姓氏或垃圾字符串作为输入),堆栈将损坏,并且可能出现seg故障。您可能需要考虑包括逻辑,以确保SaveTF不会超过您所拥有的缓冲空间。或者最好是完全避免使用sprintf
(更多信息见下文)文件*
的文件。感兴趣的I/O功能将是fopen
,fclose
,fprintf
,fwrite
,等等。这样就不需要使用sprintf
有关更多信息,请参阅。我在这里看到一些问题:
if((buflen = read(fd1, &recs, sizeof(recs))) < 0){
sprintf
不阻止写入字符串缓冲区的末尾。事实上,它不知道缓冲区的长度(在您的例子中是100字节)。由于您已经在堆栈中设置了缓冲区,如果sprintf
过度运行缓冲区(它可以使用长名字或姓氏或垃圾字符串作为输入),堆栈将损坏,并且可能出现seg故障。您可能需要考虑包括逻辑,以确保SaveTF不会超过您所拥有的缓冲空间。或者最好是完全避免使用sprintf
(更多信息见下文)文件*
的文件。感兴趣的I/O功能将是fopen
,fclose
,fprintf
,fwrite
,等等。这样就不需要使用sprintf
if((buflen=read(fd1,&recs,sizeof(recs))<0){
if((buflen = read(fd1, &recs, sizeof(recs))) < 0){
使用具有未初始化值的id
。如果((buflen=read(fd1,&recs,sizeof(recs)))<0){
使用未初始化值的id
。您有一些问题:
1) bin_记录的结构。它有char[],可能会溢出。
2) 在sprintf中,不能设置缓冲区最大大小。最好像这样使用snprintf:
read(fd1, &rec, sizeof(rec))
sprintf(buffer, 100, "%d, %s, %s, %f, %d\n", recs->id, recs->lname, recs->fname, recs->gpa, recs->iq);
3) 要使用null us填充缓冲区,请执行以下操作:
memset (buffer,'\0',100);
你有一些问题:
1) bin_记录的结构。它有char[],可能会溢出。
2) 在sprintf中,不能设置缓冲区最大大小。最好像这样使用snprintf:
read(fd1, &rec, sizeof(rec))
sprintf(buffer, 100, "%d, %s, %s, %f, %d\n", recs->id, recs->lname, recs->fname, recs->gpa, recs->iq);
3) 要使用null us填充缓冲区,请执行以下操作:
memset (buffer,'\0',100);
分段错误是由错误的内存访问引起的,由于该行上唯一的内存访问是
recs->…
,您可以假定recs没有正确初始化。请检查它是否在之前为NULL
,如果不是,请继续挖掘。bin\u记录的后期定义strncpy(缓冲区,“\0”,100);