我正在编写一个程序来读取存档文件的标题,并使用sscanf()函数打印出它的重要数据。效果应该类似于ls shell命令。
示例存档文件:
!<arch>
file1/ 1445559998 17099 88 33188 4 `
one
file2/ 1445485080 17099 88 33188 5 `
Two.
第一行是一个8-char&#34;魔术字符串&#34;将文件标识为存档,第二行和第四行是标题,第三行和第五行是文件的内容。
标题通过使用右边距(空格)保持正好60个字节的长度(在&#39;是\ n char之后)。
来自ar.h:
#include <ar.h>
struct ar_hdr /* file member header */
{
char ar_name[16]; /* '/' terminated file member name */
char ar_date[12]; /* file member date */
char ar_uid[6] /* file member user identification */
char ar_gid[6] /* file member group identification */
char ar_mode[8] /* file member mode (octal) */
char ar_size[10]; /* file member size */
char ar_fmag[2]; /* header trailer string */
};
现在我的代码。对于初学者,我希望能够打印出文件名:
file1
file2
我有这个代码来完成这个,除了我遇到了分段错误。
void parseArc(int fd_ar) // fd of archive
{
struct stat statbuf;
fstat(fd_ar, &statbuf);
char buf[statbuf.st_blksize];
char *filename;
int where;
where = 8;
while (where <= statbuf.st_size)
{
lseek(fd_ar, where, SEEK_SET);
read(fd_ar, buf, 60); // read the header
sscanf(buf, "%s/ ", filename);
printf("%s\n", filename);
where = where+60+4; // 60 for header length, 4 for file1 length
}
}
一个明显的错误是最后一行的+4。理想情况下,这将被替换为包含文件长度的变量,这是通过正确使用sscanf()获得的。
我的主要问题是,为什么我会遇到段错误?我假设它在sscanf()函数上。我已经阅读了函数API,但我无法弄清楚我是如何滥用它的。 THX。
答案 0 :(得分:3)
您从未初始化指针filename
。因此sscanf
正在尝试将从buf
提取的字符串写入内存中的随机位置。因此,段错误。
将filename
设为数组,或致电malloc
为其分配一些空间。
将sscanf
与%s
本身一起使用通常很危险,因为您可能会得到一个超过为字符串分配的空间的长字符串。这是一个缓冲区溢出,当您的客户开始使用时,它将导致需要紧急安全补丁。请改用%42s
之类的内容。
(您可能认为自己是安全的,因为buf
最多只有60个字节,但是如果它没有被终止会怎样?)
大多数编译器应该能够注意到您正在使用filename
未初始化,并警告您。 (gcc -Wall
会。)你的编译器中是否有警告?如果不是,请羞辱你。如果是,并且你收到了警告但却忽略了它,那就羞辱你了。