1

我无法弄清楚为什么我的程序无法将超过 2GB 的数据保存到文件中。我无法判断这是编程问题还是环境 (OS) 问题。这是我的源代码:

#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <math.h>
#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*-------------------------------------*/
//for file mapping in Linux
#include<fcntl.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/time.h>
#include<sys/mman.h>
#include<sys/types.h>
/*-------------------------------------*/
#define PERMS 0600
#define NEW(type) (type *) malloc(sizeof(type))
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

void write_result(char *filename, char *data, long long length){

int fd, fq;

  fd = open(filename, O_RDWR|O_CREAT|O_LARGEFILE, 0644);

  if (fd < 0) {
  perror(filename);
  return -1;
  }

  if (ftruncate(fd, length) < 0)
  {
  printf("[%d]-ftruncate64 error: %s/n", errno, strerror(errno));
  close(fd);
  return 0;
  }

  fq = write (fd, data,length);

  close(fd);

  return;

}

main()
{
long long offset = 3000000000; // 3GB
char * ttt;
ttt = (char *)malloc(sizeof(char) *offset);
printf("length->%lld\n",strlen(ttt));  // length=0
memset (ttt,1,offset);
printf("length->%lld\n",strlen(ttt));  // length=3GB
write_result("test.big",ttt,offset);
return 1;
}

根据我的测试,该程序可以生成超过 2GB 的文件,也可以分配这么大的内存。当我尝试将数据写入文件时发生了奇怪的事情。我检查了文件,它是空的,应该用 1 填充。

任何人都可以帮助我吗?

4

3 回答 3

0

我要在这里冒个险,说你的问题可能出在 memset() 上。

我认为,在 memset() 之后,最好的办法是,

for (unsigned long i = 0; i < 3000000000; i++) {
  if (ttt[i] != 1) { printf("error in data at location %d", i); break; }
}

一旦您验证了您尝试写入的数据是正确的,那么您应该考虑写入一个较小的文件,例如 1GB,看看您是否有同样的问题。消除每一个可能的变量,你就会找到答案。

于 2012-06-23T18:39:12.923 回答
0

您需要阅读更多关于 C 字符串以及做什么malloccalloc做什么的内容。

在您的原始main ttt文件中,指向malloc调用时内存中的任何垃圾。这意味着 nul 终止符(C 字符串的结束标记,二进制 0)可以位于malloc.

此外,由于malloc不会触及分配内存的每个字节(并且您要求很多),因此您可能会获得稀疏内存,这意味着在读取或写入内存之前,该内存实际上在物理上是不可用的。

calloccalloc分配并用 0 填充分配的内存。因此,它更容易失败(它触及分配的每个字节,因此如果操作系统使分配稀疏,则在填充后不会稀疏。)

这是您的代码,其中包含上述问题的修复程序。您还应该始终检查来自的返回值write并做出相应的反应。我会把它留给你...

主要的()
{
    长长偏移= 3000000000;// 3GB
    字符 * ttt;
    //ttt = (char *)malloc(sizeof(char) *offset);
    ttt = (char *)calloc( sizeof( char ), offset ); // 而不是 malloc( ... )
    如果(!ttt)
    {
        puts("calloc 失败,再见!");
        退出(87);
    }

    printf("长度->%lld\n",strlen(ttt)); // length=0(如果 calloc 没有失败,这现在可以正常工作)
    memset(ttt, 1, 偏移量);
    ttt[偏移量 - 1] = 0; // 现在它被 nul 终止了,下面的 printf 就可以工作了
    printf("长度->%lld\n",strlen(ttt)); //长度=3GB
    write_result("test.big",ttt,offset);
    返回 1;
}

Linux 大师注意...我知道稀疏可能不是正确的术语。如果我错了,请纠正我,因为我已经有一段时间没有被 Linux 细枝末节所埋没了。:)

于 2012-06-23T12:49:28.803 回答
0

看起来您正在达到 iDevice 的内部文件系统限制:ios - 具有超过 2GB 大小的资源文件的企业应用程序

2Gb+ 文件根本不可能。如果您需要存储如此大量的数据,您应该考虑使用其他一些工具或编写文件块管理器。

于 2012-06-23T17:44:58.963 回答