Компиляция для доступа к файлу на 64 бита

Я рассмотрел много ответов для компиляции кода для создания этого файлами чтения-записи вне 4 ГБ макс. позволенный файловыми смещениями на 32 бита. У меня нет удачи ни с одним из "простых" решений, которые я нахожу.

Суть, у меня есть Сервер Ubuntu 11,10 работ маленького ноутбука (архитектура Intel на 32 бита). Я пытаюсь считать unicode файл, который составляет 343 868 522 737 байтов в размере (0x50102940f1). Машина Ubuntu продолжает думать, что это намного меньше (0x102940f1), который оказывается только более низкими 32 битами измеренного файла истинных на 64 бита.

Я записал небольшую программу, которую я скомпилировал на MacOS и на поле Ubuntu. Mac, кажется, ведет себя правильно, поле Ubuntu не делает.

Небольшая программа ниже. В то время как я прокомментировал блок кода, который действительно только необходим для Mac. Среда Ubuntu скомпилирует оба прекрасные блока кода - и генерирует точно тот же ответ для обоих блоков.

// Necessary for Ubuntu build?
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
//#include <features.h>
// finish Ubuntu

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>

// Ubuntu version
off64_t fileMaxLen(FILE* fin) {
    off64_t fmaxlen = 0;
    if( (fin!=NULL) && (fseeko64(fin,0,SEEK_END) == 0) ) {
        fmaxlen = ftello64(fin);
        fprintf(stdout,"fileMaxLen(): file length is: %#lx \n",(long unsigned int)fmaxlen);
        fseeko64(fin,0,SEEK_SET);
    }
}

// Mac OS version
//off_t fileMaxLen(FILE* fin) {
//    off_t fmaxlen = 0;
//    if( (fin!=NULL) && (fseeko(fin,0,SEEK_END) == 0) ) {
//        fmaxlen = ftello(fin);
//        fprintf(stdout,"fileMaxLen(): file length is: %#lx \n",(long unsigned int)fmaxlen);
//        fseeko(fin,0,SEEK_SET);
//    }
//}

main(int argc, char* argv[]) {
    char fname[255];
    char *locale;
    FILE* f = NULL;

    locale = setlocale(LC_ALL, "");

    if( argc>=2 ) {
        // get the file for segmenting
        memset(fname, '\0', 255);
        sprintf(fname,"%s",argv[1]);
        fprintf(stdout,"Opening: %s\n",fname);
        f = fopen(fname,"r");
        fileMaxLen(f);
        fprintf(stdout,"Done!\n");
    } else {
        fprintf(stdout,"Need a filename\n");
    }
}

Сохраните отрывок как file_test.c, затем компиляция действительно проста.

gcc file_test.c

Затем выполните a.out

Какие-либо предложения для того, чтобы заставлять этот код распознать файлы кроме того граница на 32 бита? В этой точке я просто озадачен.

1
задан 12 January 2012 в 11:01

2 ответа

Согласно этому , размер long unsigned int в 32-битном Unix составляет 4 байта - может ли это быть, что значение обрезается там, где вы приводите fmaxlen (long unsigned int)? 112]

0
ответ дан 12 January 2012 в 11:01

Документацию по макросам, управляющим этим поведением, можно найти в man feature_test_macros.

Из этой документации вам нужно только установить _FILE_OFFSET_BITS в 64. Это должно переопределить off_t и функционировать как fseeko, ftello в 64-битных безопасных версиях (это не работает в 64-битных системах и перенаправляет символы в суффиксные версии 64 в 32-битных системах). системы). Это предпочтительнее прямого использования суффиксированных функций 64.

И, как сказал Сергей, приведение значения off_t к long unsigned int приведет к потере информации в 32-битных системах. Я не думаю, что есть стандартный код формата printf для off_t, поэтому вам, вероятно, лучше всего привести значение к unsigned long long int и использовать %#llx в качестве кода формата. Это должно быть предупреждением бесплатно для обоих размеров слова и не терять информацию.

0
ответ дан 12 January 2012 в 11:01

Другие вопросы по тегам:

Похожие вопросы: