为什么我的程序不能为文件节省大量(> 2GB)?

时间:2012-06-23 11:38:16

标签: c large-files

我无法弄清楚为什么我的程序无法将超过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。

任何人都可以帮助我吗?

3 个答案:

答案 0 :(得分:0)

您需要详细了解C字符串以及malloccalloc的内容。

在原始main ttt中指出调用malloc时内存中的垃圾。这意味着nul终结符(C字符串的结束标记,即二进制0)可以是malloc返回的垃圾中的任何位置。

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

calloc用0分配和填充分配的内存。由于这个原因,它更容易失败(它触及分配的每个字节,因此如果操作系统离开分配稀疏,它在{之后不会稀疏) {1}}填写它。)

这是您的代码,修复了上述问题。 您还应始终检查calloc的返回值并做出相应的反应。我会把它留给你......

main()
{
    long long offset = 3000000000; // 3GB
    char * ttt;
    //ttt = (char *)malloc(sizeof(char) *offset);
    ttt = (char *)calloc( sizeof( char ), offset ); // instead of malloc( ... )
    if( !ttt )
    {
        puts( "calloc failed, bye bye now!" );
        exit( 87 );
    }

    printf("length->%lld\n",strlen(ttt));  // length=0  (This now works as expected if calloc does not fail)
    memset( ttt, 1, offset );
    ttt[offset - 1] = 0;  // Now it's nul terminated and the printf below will work
    printf("length->%lld\n",strlen(ttt));  // length=3GB
    write_result("test.big",ttt,offset);
    return 1;
}

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

答案 1 :(得分:0)

看起来你正在达到内部文件系统对iDevice的限制:ios - Enterprise app with more than resource files of size 2GB

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

答案 2 :(得分: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,看看是否有相同的问题。消除每个可能的变量,你会找到答案。