针对多线程应用程序使用多个文件流读取同一文件

问题描述 投票:0回答:1

问题的背景: 我有一个大型二进制文件,其中包含具有独特结构的数据。该数据的单位称为“事件”。每个事件有 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() 函数的这种行为有什么解释吗?

(请注意,最小的可重现示例是单步。一旦程序开始读取事件,就会发生多线程)

c fopen fseek
1个回答
0
投票

错误是偏移计算中的溢出。您使用

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 | -502832176 | -1 | | 6 | 4550562144 | 255594848 | 0 | | 7 | 5308989168 | 1014021872 | 0 | | : | : | : | : |

由于溢出,结果

int
变为负值,
fseek()
对此并不满意。

首先,确保您的

long
的宽度超过 4 个字节。然后将乘法的至少一个操作数更改为
long
。例如这样
eventsPerThread * eventSize * 4L * k
.

最后一点:考虑使用更多空格以使代码更具可读性。

© www.soinside.com 2019 - 2024. All rights reserved.