我有一个小程序,使用系统调用打印文件内容 - 读取。
unsigned char buffer[8];
size_t offset=0;
size_t bytes_read;
int i;
int fd = open(argv[1], O_RDONLY);
do{
bytes_read = read(fd, buffer, sizeof(buffer));
printf("0x%06x : ", offset);
for(i=0; i<bytes_read; ++i)
{
printf("%c ", buffer[i]);
}
printf("\n");
offset = offset + bytes_read;
}while(bytes_read == sizeof(buffer));
现在在运行时我给出了一个不存在的文件名。 它打印出一些与环境变量混合的数据和最后的分段错误。
这怎么可能?什么是节目印刷?
谢谢, 约翰
答案 0 :(得分:7)
它正在打印垃圾,因为fd
总是被设置为-1,传递给read
并不是一件好事,因为它除了返回-1之外什么也不做。它会让你的缓冲区保持不变,这意味着当你开始时它会保留你那里的垃圾。
您可以将整个do
循环放在类似:
if (fd == -1) {
printf ("error here");
} else {
// do loop here
}
答案 1 :(得分:5)
读取返回-1因为fd无效,你将它存储在bytes_read中,这是一个无符号的size_t类型,所以你的循环打印(size_t)-1个字符,这是一个非常大的数字,比这个大得多缓冲区。因此,您打印了大部分地址空间,然后在最终到达终点并访问无效地址时获得段错误。
正如其他人提到的(没有回答你的实际问题),你应该检查打开错误的结果。例如,
int fd = open(argv[1], O_RDONLY);
if( fd < 0 ){
fprintf(stderr, "error opening %s: %s\n", argv[1], strerror(errno));
exit(1);
}
警告:如果您在调用strerror之前执行另一个系统调用或调用任何可能进行系统调用的例程(例如printf),则必须保存errno,然后将保存的副本传递给strerror。
关于你的计划的另一个注意事项:
while(bytes_read == sizeof(buffer))
这不是一个好的测试,因为读取的回报可能少于您要求的数量。您的循环应该继续,直到读取返回&lt; = 0。
答案 2 :(得分:1)
在使用之前,您应该检查open
返回的文件描述符是否有效。根据{{3}},您应该获得有效文件的非否定响应。从无效的描述符中读取可能是您问题的根源。
答案 3 :(得分:0)
成功完成后,open函数将打开文件并返回表示文件描述符的非负整数。否则,返回-1并设置errno以指示错误。所以请在进入循环之前检查fd以执行读取。