【问题标题】:c program doesn't work with large arrays sizec程序不适用于大数组大小
【发布时间】:2021-03-22 11:20:57
【问题描述】:

我有这个代码,我正在读取一个二进制 .dat 文件

static unsigned long BufferSize = 6000;
int i=0;
FILE *ptr;
unsigned long buffer2[5000031];

ptr = fopen("data.dat,"rb");
if (!ptr){
    printf("Hubo un error al leer el archivo\n");
    exit(1);
}
const size_t fileSize = fread(&buffer2, sizeof(unsigned long), 5000031, ptr);

printf("File size = %ld bytes\n", fileSize);
printf("Size of each item in bytes = %d\n", sizeof(unsigned long));

while(!feof(ptr))
{            
    printf("%lu\n", buffer2[i]);
    if (buffer2[i]== 201830034){
        printf("\n\n\n SE ENCONTRO EL ROL \n\n %lu posicion: %d\n\n\n", buffer2[i], i+1);
        
    }
    i++;
}
fclose (ptr);

我正在使用的文件具有应用程序 5.000.031 编号,当我使用 bigs 编号设置 BufferSize 时,就像之前的程序编译一样,但是运行失败并且当使用 50000 之类的数字工作“正常”时,任何想法可以是什么?

对不起,我的英语不是我的母语。

【问题讨论】:

  • 你把堆栈的盖子弄坏了,或者换句话说,buffer2 太大而无法放入堆栈。通过malloc()calloc() 使用动态分配。
  • fopen("data.dat,"rb");,你错过了`"data.rb"的双引号,导致代码变色。

标签: arrays c binary binaryfiles


【解决方案1】:

恭喜,您发现堆栈溢出!不是网站,是错误。

您的堆栈有一个可以在函数内部声明的变量的限制。尝试将此大小保持在 1MiB 以下,以避免在大多数设备上出现此错误。您可以在某些编译器和操作系统中更改此限制。

如果您需要更多空间,请使用静态变量或动态分配变量。

例如:

int main() {
    FILE *fp;

    fp = fopen("data.dat", "rb");
    if (!fp){
        printf("Hubo un error al leer el archivo\n");
        exit(1);
    }

    fseek(fp, 0L, SEEK_END);
    size_t sz = ftell(fp);
    fseek(fp, 0L, SEEK_SET);

    unsigned long *buffer = malloc(sz);
    size_t ret = fread(buffer, sizeof(unsigned long), sz / sizeof(unsigned long), fp);
    fclose(fp);

    ...
}

【讨论】:

  • 通常4 MiB的堆栈限制在哪里?在许多类 Unix 系统上,限制为 8 MiB,但在 Windows 系统上,通常仅为 1 MiB。这并不是在质疑您的诊断“数组对于堆栈来说太大了”——这无疑是事实。 OP用了500万就崩溃了,5万就OK了;这是一个很大的差距。我认为在 64 位类 Unix 机器(sizeof(unsigned long) == 8)上大约 100 万个条目或在 32 位机器(sizeof(unsigned long) == 4)上大约 200 万个条目可能没问题。使用静态数组或动态分配的数组更好。
  • 你说得对,我不知道我为什么会想到 4MiB。
  • 好吧,我发现了,ARM32 是 4MiB,我经常使用嵌入式系统,所以它通常是我的目标。
  • 在类 Unix 系统上,堆栈大小通过 ulimit 命令控制。运行ulimit -a -H 查找硬限制,运行ulimit -a -S 查找软限制。在 macOS 和 Linux 上,-s 要求提供堆栈大小(以 KiB 为单位)。普通用户可以将限制提高到硬限制; root(或其他适当特权的用户)可能能够进一步增加它。在 macOS 上,默认(软)限制为 8192 KiB (8 MiB),但可以增加到 65532 KiB(比 64 MiB 少 4 KiB)。它实际上根本不是编译器属性。这适用于台式机或服务器机器;嵌入式不同。
  • 旁白:更好的代码会使用long sz = ftell(fp); if (sz < 0 || sz > SIZE_MAX) Handle_Error();
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-08
  • 2016-02-04
  • 1970-01-01
  • 2011-12-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多