C语言 freadEx 函数详解 - 高效读取数据

本文将深入分析 C 语言中一个自定义的 fread 函数:freadEx,解析其实现原理,并解释关键代码段的功能。

函数定义:

int __fastcall freadEx(int a1, int a2, int a3, FILE *a4)
{
  int v4; // r4
  FILE *v5; // r5
  int v6; // r10
  int v7; // r3
  FILE **v8; // r11
  int v9; // r9
  int v10; // r6
  char *v11; // r8
  int v12; // r9
  int v13; // r1
  int v14; // lr
  char *v15; // r3
  unsigned int v16; // r5
  unsigned int v17; // r4
  unsigned int v18; // r6
  int v20; // [sp+Ch] [bp-1Ch]
  int v21; // [sp+10h] [bp-18h]
  int size; // [sp+14h] [bp-14h]
  int v23; // [sp+18h] [bp-10h]

  v4 = a2;
  v5 = a4;
  v6 = a3;
  v7 = 0;
  if ( dword_12B48 < 1 )
    return 0;                                   
  v8 = (FILE **)&unk_12054;
  while ( *(v8 - 3) != v5 )                     
  {
    ++v7;
    v8 += 11;
    if ( v7 >= dword_12B48 )
      return 0;
  }
  if ( v7 < 0 )
    return 0;
  v23 = a1;                                     
  v9 = (int)*(v8 - 2);
  if ( v9 )
  {
    v10 = (int)*(v8 - 1);
    size = a3 * a2;
    v11 = (char *)malloc(a3 * a2 + 6);          // 利用malloc函数开辟内存空间    a2是sizeof(参数类型)a3 是要读取的个数
    if ( v11 )
    {
      v20 = (v10 & 3) + v6 * v4;
      _aeabi_memclr(v11, v6 * v4 + 6);
      fseek(v5, v10 + v9 - (v10 & 3), 0);
      fread(v11, v10 & 3, 1u, v5);
      fseek(v5, v10 + v9, 0);
      v21 = (int)&v11[v10 & 3];
      fread(&v11[v10 & 3], size, 1u, v5);
      fseek(v5, v10 + v9 + size, 0);
      v12 = (4 - v20 % 4) % 4;
      fread(&v11[v20], v12, 1u, v5);
      if ( v12 + v20 >= 4 )
      {
        v13 = 0;
        v14 = -(v10 & 3);
        do
        {
          v15 = &v11[4 * v13];
          v17 = _byteswap_ulong(*(_DWORD *)&v11[4 * v13]);
          if ( v17 + 1 >= 2 )
          {
            v16 = ((unsigned __int8)v11[4 * v13 + 1] << 16) | ((unsigned __int8)v11[4 * v13] << 24) | ((unsigned __int8)v11[4 * v13 + 2] << 8);
            v18 = *(unsigned int *)((char *)v8 + (((unsigned __int8)*(v8 - 1) + (_BYTE)v14) & 0x1C)) ^ ((((v17 << 23) | (v16 >> 9)) >> 13) | (v16 >> 9 << 19));
            v11[4 * v13] = HIBYTE(v18);
            v15[1] = BYTE2(v18);
            v15[2] = BYTE1(v18);
            v15[3] = v18;
          }
          ++v13;
          LOBYTE(v14) = v14 + 4;
        } while ( v13 < (v12 + v20) / 4 );
      }
      _aeabi_memcpy(v23, v21, size);
      free(v11);
      return v6;
    }
    return 0;
  }
  return j_fread(a1, a2, a3, (int)v5);
}

函数分析:

  1. 校验参数: 函数首先校验全局变量 dword_12B48 的值是否小于 1。如果小于 1,则直接返回 0,表示读取失败。

  2. 查找文件信息: 随后,函数遍历全局数组 unk_12054,查找与文件指针 a4 匹配的位置。如果找不到,则返回 0,表示读取失败。

  3. 内存分配: 如果找到了匹配位置,函数会获取该位置的前两个元素,分别赋值给变量 v9v10。接着,函数根据 a2a3 计算出要分配的内存空间大小,并使用 malloc 函数开辟内存空间,将其赋值给变量 v11

  4. 文件读取: 如果内存分配成功,函数将执行以下操作:

    • 计算 v20 的值,该值代表数据在内存中的偏移量。
    • 使用 _aeabi_memclr 函数将 v11 指向的内存空间清零。
    • 通过 fseek 函数将文件指针定位到指定位置,并使用 fread 函数读取文件数据到 v11 指向的内存空间中。
    • 再次使用 fseek 函数定位文件指针,并读取剩余数据到内存空间。
  5. 数据解密: 函数中包含一段代码用于对读取到的数据进行解密,具体实现方式取决于代码中 ^ 操作的定义。

  6. 数据拷贝: 最后,函数将解密后的数据拷贝到 v23 指向的内存空间中,释放分配的内存空间,并返回成功读取的数据个数。

V10&3 的意义:

V10&3 的运算结果是 v10 对 4 取模的结果,即 v10 除以 4 的余数。该值用于计算 v20,以确定数据在内存空间中的起始位置,从而保证数据对齐,提高读取效率。

与标准 fread 函数的比较:

freadEx 函数相较于标准 fread 函数,主要做了以下优化:

  • 预分配内存: freadEx 会预先分配一块内存空间,避免频繁调用 mallocfree 函数,提高读取效率。
  • 数据对齐: 通过 v10&3 计算偏移量,保证读取的数据在内存中对齐,提高数据访问速度。
  • 数据解密: freadEx 增加了数据解密功能,能够读取加密过的文件数据。

结论:

freadEx 函数通过预分配内存、数据对齐和解密等优化措施,提升了文件读取效率。相比标准 fread 函数,freadEx 在处理特定文件格式和加密数据时,能够提供更好的性能表现。

C语言 freadEx 函数详解 - 高效读取数据

原文地址: https://www.cveoy.top/t/topic/g4p 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录