Загрузка файла с помошью malloc в память.

Тема в разделе "LANGS.C", создана пользователем ajak, 6 окт 2008.

  1. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    А сообщения компилятора всё-таки читать надо. Там же прямо написано, что достаточно включить _CRT_SECURE_NO_DEPRECATE в настройках проекта (C/C++ -> Preprocessor -> Preprocessor Definitions -> дописать в конец списка ;_CRT_SECURE_NO_DEPRECATE) - и не будет никаких ругательств.
    Объясняли же и советовали, и даже не один раз. Я в #18 и #20, scf в #37; более того, неоднократно советовали проверять возвращаемые значения функций malloc и fopen,fread (varnie в #12, #14, #29, Booster в #28).
    Известно, что на 118148 байт программа работает, а на 118149 вылетает. Мне кажется, что у товарища просто malloc возвращает NULL при запросе большого количества памяти. Из-за преобразования аргумента long -> size_t при вызове malloc реально идёт попытка выделить 118148 - 65536 = 52612 байт в первом случае и 52613 байт во втором. Учитывая размер сегмента в 64К и то, что в сегменте находится ещё много чего (что именно, зависит от модели памяти - в tiny-модели, например, весь код, данные, стек, а в начале сегмента ещё и данные системы aka PSP, которые нельзя трогать), вариант с банальной нехваткой памяти выглядит логично. Соответственно при таком раскладе 118148 - не единственный "критический" размер, тот же самый эффект будет и при файле на 52612 байт (любом!), и при файле на 52612+2*65536 = 183684 байт.
     
  2. scf

    scf Member

    Публикаций:
    0
    Регистрация:
    12 сен 2005
    Сообщения:
    386
    Тьфу ты блин, совсем забыл, что в обычной модели(не FAR и не tiny) под все данные программы выделяется один сегмент DS:xxxx, т.е. до 64К
    Было же время :)
    Автору погуглить про модели памяти дос-программ(см. настройки компилятора - memory model) и сегментную организацию памяти в MS-DOS/реальном режиме. что такое сегмент, что такое смещение и как адресуются байтики в памяти.
     
  3. ajak

    ajak New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2007
    Сообщения:
    463
    Ладно, коль так, очень прошу, Вас товарищи, напишите готовый пример на си, хоть для доса, хоть для студии, только без апи. У меня проект стоит и ничего не получается. Приведите пример чтобы можно было прочитать середину того большого файла на 500 кило, ссылка которого приведена ранее первой. ОЧень на Вас надеюсь, т.к. я все свои ресурсы исчерпал. Спасибо.
     
  4. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    ajak
    Код (Text):
    1. /* fread example: read a complete file */
    2. #include <stdio.h>
    3. #include <stdlib.h>
    4.  
    5. int main () {
    6.   FILE * pFile;
    7.   long lSize;
    8.   char * buffer;
    9.   size_t result;
    10.  
    11.   pFile = fopen ( "myfile.bin" , "rb" );
    12.   if (pFile==NULL) {fputs ("File error",stderr); exit (1);}
    13.  
    14.   // obtain file size:
    15.   fseek (pFile , 0 , SEEK_END);
    16.   lSize = ftell (pFile);
    17.   rewind (pFile);
    18.  
    19.   // allocate memory to contain the whole file:
    20.   buffer = (char*) malloc (sizeof(char)*lSize);
    21.   if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
    22.  
    23.   // copy the file into the buffer:
    24.   result = fread (buffer,1,lSize,pFile);
    25.   if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
    26.  
    27.   /* the whole file is now loaded in the memory buffer. */
    28.   //здесь делаем с считанным файлом в память что хотим.
    29.  
    30.   // terminate
    31.   fclose (pFile);
    32.   free (buffer);
    33.   return 0;
    34. }
     
  5. scf

    scf Member

    Публикаций:
    0
    Регистрация:
    12 сен 2005
    Сообщения:
    386
    varnie
    Не будет это работать для больших файлов под ДОСом

    Я даже не поленился сваять под BC3.1 небольшую прогу:
    Код (Text):
    1. #include <stdio.h>
    2. #include <stdlib.h>
    3.  
    4. int main()
    5. {
    6.   printf("\n\n");
    7.   FILE *f = fopen("d:\\1.dat", "rb");
    8.   if (f == NULL)
    9.   {
    10.     printf("file not found\n");
    11.     return -1;
    12.   }
    13.   fseek(f, 0, SEEK_END);
    14.   long len = ftell(f);
    15.   printf("size of int=%i\n", sizeof(int));
    16.   printf("file size=%li\n", len);
    17.   unsigned int sum = 0;
    18.   unsigned char *buf = (unsigned char *)malloc(32768);
    19.   fseek(f, 0, SEEK_SET);
    20.   while (1)
    21.   {
    22.     size_t read = fread(buf, 1, 32768, f);
    23.     if (!read) break;
    24.     for (int i = 0 ; i < read ; i++)
    25.       sum += buf[i];
    26.   }
    27.   printf("control sum=%X\n", sum);
    28.   long off = len / 2;
    29.   printf("reading 10 bytes at off %li\n", off);
    30.   fseek(f, off, SEEK_SET);
    31.   fread(buf, 1, 10, f);
    32.   printf("bytes: ");
    33.   for (int i = 0 ; i < 10 ; i++)
    34.     printf("%2X ", buf[i]);
    35.   free(buf);
    36.   fclose(f);
    37.   return 0;
    38. }
    Вывод:
    Код (Text):
    1. size of int=2
    2. file size=27475828
    3. control sum=EE1F
    4. reading 10 bytes at off 13737914
    5. bytes: CE BA C6 B7 32 47 25 EB F7 BE
    Естестенно, байты совпадают с тем, что показывает HIEW
     
  6. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    ajak
    Ты упорно бъешся головой об стену вместо того, чтобы решить вопрос кардинально. Ограничение на макс.размер есть не только в досе, но и в винде - только в досе это десятки килобайт, а винде 1.5-2Г. Но никто от этого шибко не переживает, т.к. большие файлы обычно читают\обрабатывают\записывают не целиком, а блоками. Читай поблочно и будет тебе счастие :)
    PS: Если все-же нужно грузить файл целиком, то совершенно необязательно писать его в один непрерывный массив - можно организовать sparse array в виде массива (или списка) массивов некоторого фикс.размера
     
  7. ajak

    ajak New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2007
    Сообщения:
    463
    Спасибо парни, сегодня обязательно приду проверю.
    А как же эмуляторы сеги под ДОС?
    Я не люблю исходники смотреть, но пришлось их посмотреть. Так там весь файл сразу читается в память и всё работает под дос. Что на это скажете?
    А как вам Рестл-мания или МК Ультимэйт, там вообще образ рома 4,5 мега или около 4.
    Читается всё сразу чтоб эмулятор быстрее работал. Спасибо всем всё равно. Вечером отпишусь.
     
  8. ajak

    ajak New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2007
    Сообщения:
    463
    Да, кстати, как можно поблочно читать - так запаришся. Допустим там джамп стоит на самый конец рома, а в этом конце опять джамп наверх. Здесь уже нужно поспорить про поблочность.
     
  9. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Ну и что, есть же проги которые из реального переходят в защищённый. Уж очень реальный режим геморойный, отстой да и только. Нафига под дос делать, хочешь выгадать немного производительноси? Так в фулскрине производительности почти равна той, что в реальной оси, а про эмуляцию доса в винде вобще молчу, сплошной тормоз и глюкан. Переходи на нормальный компиль, (если просто скомпилишь свою прогу компилем от майкрософта, производительнось сильно поднимется, а про интел вобще молчу). Пиши под DirectX или OpenGL, и не кампостируй мозг.
     
  10. ajak

    ajak New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2007
    Сообщения:
    463
    Код (Text):
    1. Нафига под дос делать
    А как под винду делать скажи, без апи только ?
     
  11. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    А что ты так API боишься? Работа с файлами абсолютно кросплатформенна. Открываешь студию, создаёшь консольный проект и вперёд с песней. Если нужны платформозависимые вещи, то для этого есть кросплатфоменные библиотеки. А можно и макросредства заюзать для этого. Библ. кросплатформенных валом.
     
  12. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    ajak
    брр.. теперь точно ничего не понятно. тебе же надо в буфер файл считать -- какие нафик тут джампы? у тебя что, дизассемблер чтоли? я тебя не понимаю.
    почитай "Язык С++" от Б.Страуструпа. нафик тебе winAPI, работай с самим языком С++.

    и, как правильно уже заметили, смени компилятор ^_^
     
  13. ajak

    ajak New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2007
    Сообщения:
    463
    Уже сменил, поставил дополнительно студию 6.
    Пардон, не понял, т.е. допустим я выделил область на 512 кило.
    И могу туда по блокам 2 раза считать по 256? Так чтоли?
     
  14. ajak

    ajak New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2007
    Сообщения:
    463
    А что есть не писать под дос. Мля. Я же не использую прерывания. Что, если я использую старый компиль и ide, то это значит что я пишу под дос получается?
     
  15. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    ajak
    да. можешь считать 512кб за два присеста и осуществить запись в свой выделенный буфер два раза, по 256кб. можешь хоть по байту читать, и писать в буфер. тогда 512 раз будет =) как тебе удобнее в общем...
    создай в студии консольное приложение и пиши свой код там. всё. будет 100% виндовое приложение. что такое старый компиль я не знаю. почитай хелп по этому компилеру старому и все станет ясно.
     
  16. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    BC 3.1 умеет собирать, только ДОС проги. Винда видит что это ДОС, и фигачит его в ntvdm. Студия собирает нормальный PE файл, и создаёт нормальный win32 битный процесс, со всеми вытекающими.
     
  17. ajak

    ajak New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2007
    Сообщения:
    463
    Кайф, не знал. То-то у меня вылетает, что-то связанное с файлом
    ntvdm. А что это, и что он делает я вообще не в курсе. Наверное эмуляция памяти. БУдем знать что борланд не собирает полноценный ПЕ.
     
  18. ajak

    ajak New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2007
    Сообщения:
    463
    Считаю тему исчерпанной, единственное вот что. Откомпили прогу из поста 44 и получаю такие результаты.
    Когда читаю файл размером 524288 - пишет Memory error. Когда файл размером 118 148 - пишет Reading error.
    А КОГДА ФАЙЛ 1 МЕГАБАЙТ забитый только буквой 'А' - то всё нормально %/
     
  19. varnie

    varnie New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2005
    Сообщения:
    1.785
    ajak
    у тебя это в мегах указаны размеры: 524288, 118 148? или кб??
     
  20. ajak

    ajak New Member

    Публикаций:
    0
    Регистрация:
    24 окт 2007
    Сообщения:
    463
    118148 кило. ВСё в кило