因此,我有一个函数,它需要一个偏移量和一个宽度从设备(通常是硬盘)读取。现在,我使用fseeko()和fread()从磁盘读取。不过,我想用更简明扼要的措辞来代替这一点。然而,无论如何,扩展总是从偏移量0读取。
下面是函数的代码:
只是提个醒。我确实有
#define _FILE_OFFSET_BITS 64
在我的密码顶端。我也用同样的结果尝试了pread64()!
对于fread(),这做了我想要的!:
uint8_t retrievedata(FILE *fp,uint64_t seekpoint, uint64_t seekwidth) {
unsigned char buf[seekwidth];
if(fseeko(fp,seekpoint,SEEK_SET)==0) {
if(fread(buf,sizeof buf,1,fp)==1) {
/* do work with retrieved data */
}
else {
printf("ERROR READING AT: %"PRIu64"| WITH VAL WIDTH: %"PRIu64"\n",seekpoint,seekwidth);
return 4;
}
}
else {
printf("ERROR SEEKING AT: %"PRIu64"\n",seekpoint);
return 3;
}
}
,无论“查找点”是什么,它总是从偏移量0读取:
uint8_t retrievedata(FILE *fp,uint64_t seekpoint, uint64_t seekwidth) {
unsigned char buf[seekwidth]
if (pread(fileno(fp),buf,seekwidth,seekpoint)!=-1) {
/* do something */
} else {
printf("ERROR SEEKING AND/OR READING AT: %"PRIu64"\n",seekpoint);
return 3;
}
}
发布于 2014-03-19 22:13:43
启用编译器警告(GCC的-W -Wall
),并阅读手册页中的“GLIBC的特性测试宏要求”部分。
这些警告表明您错过了所需的另一个宏定义,man 2 pread
手册页告诉您,您还需要的宏定义是
#define _POSIX_C_SOURCE 200809L
要获得GNU库版本2.12或更高版本以正确声明pread()
等。
你所看到的行为,是因为你没有这样的声明。
我想告诉大家我是如何理解整个故事的,因为我希望它能准确地告诉您,通过阅读和理解手册页,以及更重要的是,通过启用和处理编译器警告,您可以节省多少精力和精力。
我知道你认为你现在没有时间去做所有的事情(也许稍后,对吧?),但是你错了:当为Linux编写C(或者一般的类似POSIX的系统)时,这是节省时间的最好方法之一。
我自己总是和GCC一起用-W -Wall
。这只会使我们更容易找到问题的根源所在。现在,你把注意力集中在最主要的症状上,因为编程不是政治(还没有),它不会给你带来任何好处。
所以,全貌:
fread()
返回读取的元素数。在您的示例中,您读取了一个seekwidth
字节元素,并验证了一个元素是否正确读取。
pread()
返回读取的字节数。第二个代码片段尝试读取从偏移量seekwidth
开始的seekpoint
字节,但不检查实际读取了多少数据,只检查是否发生错误。
以下是我认为你正在发生的事情:
#define _POSIX_C_SOURCE 200809L
声明(在#include <unistd.h>
之前),以使pread()
函数原型声明。pread
的隐式声明”警告。-m32
GCC选项编译32位体系结构。如果没有函数原型,编译器假设pread()
函数的所有参数都是ints -因此是32位--并且只向pread()
提供一个32位的seekpoint
值。前三个参数( int、指针和size_t)碰巧都是32位,但是第四个参数文件偏移量是64位。(请记住,您使用#define _FILE_OFFSET_BITS 64
告诉了您的C库。)
这意味着pread()
接收的64位文件偏移量是垃圾。(这取决于字节顺序--小endian或Intel,或大端或Motorola/PowerPC/ARM-以及特定的体系结构二进制接口(ABI)如何将第四个参数传递给函数,值是如何被混淆的。)
在这种情况下,我认为您的目标是32位英特尔体系结构,通常pread()
实际接收的值(以乱码表示)大于文件大小,因此pread()
返回0:“过去的文件结束,没有更多的数据可读取”。
您的代码忽略了这一点(因为它不是-1),而是假设它成功地读取了数据。您所看到的数据很可能是以前读取的数据--如果缓冲区返回0,pread()
不会修改它。
(这种情况也有其他可能的变体;甚至有些情况下,pread()
总是接收零作为(混淆的)偏移量。实际上,这并不重要,因为在所有情况下,拥有适当的功能原型都可以解决问题。您也需要检查pread()
返回值,因为无法保证它将实际读取所请求的字节数。它经常这样做,是的;但是没有任何保证,所以请不要做出毫无根据的假设。)
https://stackoverflow.com/questions/22518536
复制相似问题