C语言 使用多线程应用程序的多个文件流阅读同一文件

q3qa4bjr  于 2023-10-16  发布在  其他
关注(0)|答案(1)|浏览(124)

**问题的上下文:**我有一个包含具有唯一结构的数据的大型二进制文件。这种数据的一个单元称为“事件”。每个事件有32016字节,一个文件包括大约400000个事件,使文件~12 GB。我正在编写一个程序来处理这些事件,并尝试使用多线程方法,让多个线程阅读文件的不同部分(让每个线程使用自己的文件流)。

问题是fseek无法找到文件的正确位置。以下是最小可再现的示例。该程序读取一个二进制文件与473797事件计划使用20胎面,而每个胎面使用不同的文件流。

#include <iostream>
#include <stream>
#include <errno.h>
#include <string.h>

using namespace std;

int main(){

        FILE *segment[20];
        int ret=0;
        int eventsPerThread=473797/20;
        int eventSize=8004;
        for(int k=0;k<20;++k){
                segment[k]=fopen("Datafile_367.bin","rb");
                if(segment[k]==NULL){
                        std::cout<<"file stream is NULL!"<<k<<"\n";

                }

                ret=fseek(segment[k],eventsPerThread*eventSize*4*k,SEEK_SET);
                std::cout<<ret<<":::"<<strerror(errno)<<"\n";

        }
                return 0;
}

以下是输出。fseek有时成功,返回0,而在其他时候失败,错误代码为22(无效参数)。

0:::Success
0:::Success
0:::Success
-1:::Invalid argument
-1:::Invalid argument
-1:::Invalid argument
0:::Invalid argument
0:::Invalid argument
0:::Invalid argument
-1:::Invalid argument
-1:::Invalid argument
-1:::Invalid argument
0:::Invalid argument
0:::Invalid argument
0:::Invalid argument
-1:::Invalid argument
-1:::Invalid argument
0:::Invalid argument
0:::Invalid argument
0:::Invalid argument

对fseek()函数的这种行为有什么解释吗?
(Note最小的可重复例子是单个胎面。一旦程序开始读取事件,就会发生多线程)

oyjwcjzk

oyjwcjzk1#

错误是偏移计算中的溢出。您使用int,它显然是4个字节宽。INT_MAX是2147483647这个宽度。
让我们看看:
| K| eventsPerThread * eventSize * 4 * k|溢出int|返回值fseek()|
| --|--|--|--|
| 0 | 0 | 0 | 0 |
| 1 | 758427024 | 758427024 | 0 |
| 2 | 1516854048 | 1516854048 | 0 |
| 3 | 2275281072 |2019686224|-1个|
| 4 | 3033708096 |电话:1261259200|-1个|
| 5 | 3792135120 |粤ICP备0502832176号|-1个|
| 6 | 4550562144 | 255594848 | 0 |
| 7 | 5308989168 | 1014021872 | 0 |
| :|:|:|:|
由于溢出,结果int变为负值,fseek()对此不满意。
首先,确保long的宽度大于4个字节。然后将乘法的至少一个操作数更改为long。例如,eventsPerThread * eventSize * 4L * k

  • 最后说明:考虑使用更多的空格,使您的代码更具可读性。

相关问题