Joh*_*ohn 2 c unix system-calls
我有一个小程序,使用系统调用打印文件的内容 - 读取.
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));
Run Code Online (Sandbox Code Playgroud)
现在,在运行时,我给出了一个不存在的文件名.它打印出一些与环境变量混合的数据和最后的分段错误.
这怎么可能?什么是程序打印?
谢谢,约翰
它是打印垃圾,因为它fd总是被设置为-1,这不是一件好事,read因为它会反过来除了返回-1之外什么也不做.它会让你的缓冲区不受影响,这意味着当你开始时它会保留你在那里的垃圾.
您可以将整个do循环放在以下内容中:
if (fd == -1) {
printf ("error here");
} else {
// do loop here
}
Run Code Online (Sandbox Code Playgroud)
read返回-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);
}
Run Code Online (Sandbox Code Playgroud)
需要注意的是:如果您在调用strerror之前执行另一个系统调用或调用任何可能进行系统调用的例程(例如printf),则必须保存errno,然后将保存的副本传递给strerror.
关于你的计划的另一个说明
while(bytes_read == sizeof(buffer))
Run Code Online (Sandbox Code Playgroud)
这不是一个好的测试,因为读取的回报可能低于您要求的数量.您的循环应该继续,直到读取返回<= 0.
| 归档时间: |
|
| 查看次数: |
882 次 |
| 最近记录: |