c - sprintf() 期间的段错误

标签 c systems-programming

因此,我目前正在为我的 Unix 操作系统类(class)进行系统编程。该程序应该做的就是读取二进制文件并将行输出到 CSV 文件。我觉得我快完成了,但出于某种原因,我一直遇到段错误。

澄清一下: fd1 = 输入文件, fd2 = 输出文件, numrecs = 来自输入文件的记录数。 在 main() 的某处:

for(i=0;i<numrecs;i++){
    if((bin2csv(fd1, fd2)) == -1){
        printf("Error converting data.\n");
    }
}

int bin2csv(fd1, fd2){
    bin_record rec;
    char buffer[100];
    int buflen;
    strncpy(buffer,"\0", 100); /* fill buffer with NULL */
    recs = &rec;

    /* read in a record */
    if((buflen = read(fd1, &recs, sizeof(recs))) < 0){
        printf("Fatal Error: Data could not be read.\n");        
        return -1;
    }

   sprintf(buffer, "%d, %s, %s, %f, %d\n", recs->id, recs->lname, recs->fname, recs->gpa, recs->iq);
   printf("%s\n", buffer);
   write(fd2, buffer, sizeof(buffer));
   return 0;
}

段错误发生在“sprintf(buffer, etc..);”行但是,我不明白为什么会这样。

这是 gdb 吐出的错误:

Program received signal SIGSEGV, Segmentation fault.
0x0000000100000c87 in bin2csv (fd1=3, fd2=4) at bin2csv.c:25
25 sprintf(buffer, "%d, %s, %s, %f, %d\n", recs->id, recs->lname,
recs->fname, recs->gpa, recs->iq);

希望这是足够的信息。谢谢!

最佳答案

看起来recs 是一个指针。您正在将字节直接读入该指针,就像从文件中读取原始内存地址一样:

read(fd1, &recs, sizeof(recs))

然后您开始在对 sprintf 的调用中使用它... BOOM!

实际上根本没有理由使用它(它是全局的吗?)...即使您通过 recs = &rec 初始化它,并且假设您不丢弃它,它仍然不会包含该函数之外的有效地址。那是因为 rec 是一个局部变量。

所以,像这样直接读入rec:

read(fd1, &rec, sizeof(rec))

然后在 sprintf 行中,您使用 rec.id 而不是 recs->id(等等).

关于c - sprintf() 期间的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34305369/

相关文章:

C - 二进制读取,fread 是反转顺序

c++ - 为给定的整数递增单个数字 (msb)

windows - SysInternals WinObj 设备列表机制

c - Unix系统编程: get a network identifier to be passed to getaddrinfo

c++ - 直接跳转到另一个C++函数

c - 目录中文件的链接列表,最后附加

c - RET 之后的指令是否总是 CALL 之后的指令?

mysql - zlib 和 MySQL UDF

unix - 无法进入系统调用源代码

c - 如何对管道中的数据调用 UNIX 排序命令