【问题标题】:malloc sometimes fails. or pread sometimes failsmalloc 有时会失败。或 pread 有时会失败
【发布时间】:2014-05-01 06:00:25
【问题描述】:

所以我有一个测试程序,它将大量数据读入缓冲区并分配 相应地缓冲。但是它 malloc 在大尺寸上失败了。

有没有办法解决这个问题?

感谢任何回复

设备 /dev/sdc 是 2TB 磁盘。

这里准备好2个编译代码:

#define          _FILE_OFFSET_BITS                            64     
#define          BLKGETSIZE64                                _IOR(0x12,114,size_t)    
#define          _POSIX_C_SOURCE                             200809L

#include <stdio.h>    
#include <inttypes.h>    
#include <stdlib.h>    
#include <fcntl.h>    
#include <unistd.h>

int readdata(int fp,uint64_t seekpoint, uint64_t seekwidth) {

    int16_t  *buf;

    buf=(int16_t *)malloc(seekwidth*sizeof(int16_t)+1);
    if (buf==0) {
      printf("ERROR malloc(%"PRIu64")\n",seekwidth*(sizeof(int16_t)));
      return 3;
    }

    if (pread(fp,buf,seekwidth,seekpoint)==seekwidth) {
        printf("SUCCES READING AT: %"PRIu64"| WITH READ WIDTH: %"PRIu64"\n",seekpoint,seekwidth);
        free(buf);
        return 1;
    } else {
        printf("ERROR READING AT: %"PRIu64"| WITH READ WIDTH: %"PRIu64"\n",seekpoint,seekwidth);
        free(buf);
        return 2;
    }

}



int main() {
    uint64_t    readwith,
                offset;
    int         fp=open("/dev/sdc",O_RDWR);

    readwith=10000;   offset=0;
    readdata(fp,offset,readwith);
    readwith=100000;   offset=0;
    readdata(fp,offset,readwith);
    readwith=1000000;   offset=0;
    readdata(fp,offset,readwith);
    readwith=10000000;   offset=0;
    readdata(fp,offset,readwith);
    readwith=100000000;   offset=0;
    readdata(fp,offset,readwith);
    readwith=1000000000;   offset=0;
    readdata(fp,offset,readwith);
    readwith=10000000000;   offset=0;
    readdata(fp,offset,readwith);
    close(fp);

}

我系统上的输出是:

SUCCES READING AT: 0| WITH READ WIDTH: 10000
SUCCES READING AT: 0| WITH READ WIDTH: 100000
SUCCES READING AT: 0| WITH READ WIDTH: 1000000
SUCCES READING AT: 0| WITH READ WIDTH: 10000000
SUCCES READING AT: 0| WITH READ WIDTH: 100000000
SUCCES READING AT: 0| WITH READ WIDTH: 1000000000
ERROR READING AT: 0| WITH READ WIDTH: 10000000000
ERROR READING AT: 0| WITH READ WIDTH: 100000000000
ERROR READING AT: 0| WITH READ WIDTH: 1000000000000
ERROR READING AT: 0| WITH READ WIDTH: 10000000000000
ERROR READING AT: 0| WITH READ WIDTH: 100000000000000
ERROR READING AT: 0| WITH READ WIDTH: 1000000000000000

有时

ERROR malloc(2000000000)
ERROR READING AT: 0| WITH READ WIDTH: 10000000000

【问题讨论】:

  • 既然这是/dev/sdc,我猜它是一个闪存驱动器?也许您正在尝试分配比它更多的内存?另外,它在哪一边失败了?
  • 这是一个 2TB 磁盘,我在我的系统上添加了输出
  • 您应该在malloc 或pread 等失败时打印strerror(errno)...

标签: c linux memory-management malloc


【解决方案1】:

好吧,我想说你不能分配大小为 10000000000 的内存,因为那是 9536 MiB,我猜你没有那么多 RAM。

您可以考虑使用STXXL。

STXXL 的核心是 C++ 标准模板的实现 用于外部存储器(核外)计算的库 STL,i。例如, STXXL 实现了可以处理海量的容器和算法 只适合磁盘的数据量。

【讨论】:

    【解决方案2】:

    Doug lea malloc(dlmalloc) 关于chunk的最小和最大尺寸

    如果 n 为零,malloc 返回一个最小大小的块。 (最小尺寸 在大多数 32 位系统上是 16 字节,在 64 位系统上是 32 字节。) 请注意, size_t 是无符号类型,因此使用以下参数调用 如果签名被解释为巨额请求,则为负数 大量的空间,这通常会失败。 支持的最大值 的 n 因系统而异,**但在所有情况下都小于最大值 size_t 的可表示值。

    最大块大小可以是 (2^31) 及其左右 2147483648。

    因此,在您的情况下,最后一次成功的 malloc 调用是 1000000000*2 大于最大值,因此 malloc 返回 NULL。

    【讨论】:

      【解决方案3】:

      如果你想对整个磁盘或大文件上的数据做一些事情,你可能想改用mmap(2)。

      来自手册页:

      mmap() 在虚拟地址空间中创建一个新的映射 调用进程。

      int fd = open("/dev/sdc", O_RDONLY);
      unsigned char *data = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0);
      

      如果您希望能够写入磁盘,事情会变得更加棘手和危险,但这也是可能的(有关详细信息,请参阅mmap(2) 手册页。)

      【讨论】:

      • 这似乎是个好主意。但是如果我关闭 fd 或磁盘从系统中删除,它会如何处理?
      • 为什么要在完成之前关闭 fd?至于磁盘是否被移除,您的程序在尝试访问它时可能会收到SIGBUS 或SIGSEGV 之类的信号(您可能能够捕获和处理)。但是,如果您认为这很有可能,那么您可能还没有解释您实际上要做什么。
      猜你喜欢
      • 2016-04-17
      • 2011-08-10
      • 2016-06-21
      • 2010-12-06
      • 2015-08-22
      • 1970-01-01
      • 1970-01-01
      • 2020-10-17
      • 1970-01-01
      相关资源
      最近更新 更多