0xC0000017

Тема в разделе "WASM.HEAP", создана пользователем icent, 5 авг 2009.

  1. icent

    icent New Member

    Публикаций:
    0
    Регистрация:
    23 апр 2009
    Сообщения:
    154
    Cледующая не хорошая ситуация..: тривиальный код (дефайны заменены на числа, с ними все в порядке):

    Код (Text):
    1. heap = HeapCreate(HEAP_GENERATE_EXCEPTIONS,
    2.             100*15*12,
    3.             0); // выделяет обычно 0x00380000 (0x00400000 - ImageBase)
    4.                 // память доступна по 0x00384FF0
    5.  
    6. /*.......... потом вызов другой ф-ии (HANDLE heap передается), внутри неё: */
    7.  
    8. // allocate memory
    9. new_heap=HeapAlloc(heap, HEAP_ZERO_MEMORY, 100*12);
    При первом аллоке возвращает 0x00381EA0 - это понятно.
    При втором: Unhandled exception at 0x7c93b4ed (ntdll.dll) in [blah.exe]: 0xC0000017: Not Enough Quota.

    MSDN говорит:

    "Error Message:

    (Not Enough Quota) Not enough virtual memory or paging file quota is available to complete the specified operation.
    User Action:

    This is a Windows 2000 Executive STATUS error message. Try running the application again. If this message reappears, contact your system administrator to adjust your paging file size or your quota."


    Гугл говорит, что надо поискать другие пути выделения памяти, потому что происходит утечка памяти.. (%

    Естественно, если создать чистый проект и выделять подобным образом память - все четко.
    Проект не такой уж большой.. Даже не средний. Скорее чуть больше, чем маленький)

    Кто сталкивался?

    В одном вялом обсуждении нашел что-то про PGFLQUOTA или PQL_DPGFLQUOTA.
    Я запускаю под админом, при чем на разных компах - результат тот-же.

    Если юзать malloc - проблема та-же.
     
  2. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    Ф-цию в студию
     
  3. icent

    icent New Member

    Публикаций:
    0
    Регистрация:
    23 апр 2009
    Сообщения:
    154
    Пожалуйста. Это кусочек парсера импорта. heap, как я уже говорил, был выделен ранее. Никакой работы памятью больше нету. Даже не знаю, чем поможет листинг.. но раз пр0сите:

    Код (Text):
    1. DWORD read_import(PEF_PTRS ef_ptrs, void *ptr_img, HANDLE heap)
    2. {
    3.     /*
    4.         Читает импорт одного файла и заполняет
    5.         соответствующие структуры lyb_entry's.
    6.     */
    7.  
    8.     char *lib_name[20];
    9.     BOOL exist = FALSE;
    10.     PLIB_LIST_ENTRY lib_entry;
    11.  
    12.     PIMAGE_IMPORT_DESCRIPTOR Import =               \
    13.         (PIMAGE_IMPORT_DESCRIPTOR)                  \
    14.         ((((PIMAGE_NT_HEADERS)                      \
    15.         ((((PIMAGE_DOS_HEADER)ptr_img)->e_lfanew)+  \
    16.         (int)ptr_img))->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)+ \
    17.         (int)ptr_img);
    18.  
    19.     while (Import->Characteristics) // main cycle
    20.     {
    21.         strcpy((char *)lib_name,(char *)((Import->Name)+(int)ptr_img));
    22.         strlwr((char *)lib_name);
    23.  
    24.         if (must_dll((char *)lib_name)) {
    25.  
    26.             lib_entry = ef_ptrs->ptr_lib_entrys;
    27.  
    28.             // Is lib entry already in list?
    29.             //
    30.             for (int i = 0; i < ef_ptrs->lib_entrys_count; i++)
    31.             {
    32.                 if (!(strcmp(lib_entry->lib_name,(char *)lib_name)))
    33.                 {
    34.                     exist=TRUE;
    35.                     lib_entry->counter++;   // up library rate
    36.                     break;
    37.                 } // if
    38.                 lib_entry++;
    39.             } // for
    40.  
    41.             if (!exist) // create new entry
    42.             {
    43.                 strcpy(ef_ptrs->ptr_lib_names + ef_ptrs->lib_names_size,(char *)lib_name);
    44.                 lib_entry->lib_name = ef_ptrs->ptr_lib_names + ef_ptrs->lib_names_size;
    45.                 ef_ptrs->lib_names_size += strlen((char *)lib_name)+1;
    46.                
    47.                 lib_entry->counter = 0;
    48.                 // allocate memory fo API_LIST_ENTRY
    49.                 [b]lib_entry->ptr_api_list=(PAPI_LIST_ENTRY)HeapAlloc(heap,
    50.                                         HEAP_ZERO_MEMORY,
    51.                                         MAX_API*sizeof(API_LIST_ENTRY));[/b]
    52.  
    53.                 if (!lib_entry->ptr_api_list) return(ERROR_INVALID_ADDRESS);
    54.  
    55.                 lib_entry->api_list_count=0;
    56.                
    57.                 ef_ptrs->lib_entrys_count++;
    58.             } // **********************
    59.  
    60.             // The lib_entry is set up. Read them.
    61.             //
    62.             read_import_descriptor(ef_ptrs, Import, (DWORD)ptr_img, lib_entry);
    63.  
    64.         } // end if (must dll)
    65.  
    66.         Import++;   // next IMAGE_IMPORT_DESCRIPTOR entry
    67.  
    68.     } // main cycle
    69.    
    70.     return 1; //копибара отсюдава
    71. }
     
  4. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    Предполагаю, что цикл в read_import бегает дольше чем необходимо, и просто тупо выжирается вся доступная память.
     
  5. icent

    icent New Member

    Публикаций:
    0
    Регистрация:
    23 апр 2009
    Сообщения:
    154
    Это происходит на _втором_ проходе при чтении _первого_ файла. В первом посту даже адреса приведены.
     
  6. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    Да хоть на 10м. Проблема в ф-ции read_import, больше ей негде быть ( из тех данных, что приведены ).
    Статус STATUS_NO_MEMORY говорит нам, что либо поврежден хип, либо недостаточно памяти ( что вернее всего ).
    Советую отладчиком пройтись по этой ф-ции и посмотреть, что конкретно там не так.
     
  7. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    Кстати, если куча создана с флагом HEAP_GENERATE_EXCEPTIONS, то неплохо было бы исключения то ловить всеже, иначе зачем ставить флаг.
     
  8. icent

    icent New Member

    Публикаций:
    0
    Регистрация:
    23 апр 2009
    Сообщения:
    154
    Ты думаешь я не отлаживал ф-ию прежде чем создать топик на форуме? Ф-ия не работет с памятью и не выделяет её более 1-го раза. При второй попытке происходит крэш.

    На данный момент код тестовый. Я пробовал все флаги. Разницы совершенно никакой. Под отладкой все видно.
     
  9. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    Ок, если память выделяется корректно, значит остается вариант с её повреждением.
     
  10. icent

    icent New Member

    Публикаций:
    0
    Регистрация:
    23 апр 2009
    Сообщения:
    154
    Всмысле? Физическим повреждением? о_О Но ведь..
     
  11. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    Всмысле куча повреждена, например если в ф-ции read_import_descriptor (куда передается указатель на структуру содержащую выделенную память) есть запись блока данных размером больше чем MAX_API*sizeof(API_LIST_ENTRY).
     
  12. icent

    icent New Member

    Публикаций:
    0
    Регистрация:
    23 апр 2009
    Сообщения:
    154
    А, понятно.. А разве в таком случае не произойдет экспшна при попытке записи выше кучи? Сейчас не могу посмотреть, к сожалению. По-идее не должно быть такого, т.к. там было всего-лишь 15 ф-ий, а 15*sizeof(API_LIST_ENTRY)=180, а выделяется под одну библиотеку 1200. Но, конечно, завтра проверю.
     
  13. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    icent
    Хип не следует юзать. Выделяйте память сервисами(NtAllocateVirtualMemory) либо через экспорт/стуб Zw*
    Ваша ошибка довольно редкая, обойти её не удастся, если в ядре не достаточно памяти, тогда можно попытаться использовать секции(дисковое пространтсво, своп).
     
  14. icent

    icent New Member

    Публикаций:
    0
    Регистрация:
    23 апр 2009
    Сообщения:
    154
    Clerk
    Т.е. баг кроется в фантиках kernel32.dll для NtAllocateMemory?

    Да.. вспомнилось:
    Правда, иногда возникают сложные проблемы. Я вижу, как они появляются, я останавливаюсь, я наблюдаю. Затем я меняю одну строку кода и сложности исчезают, как клуб дыма. [C] James Geoffrey
     
  15. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    icent
    Хип это громоздкая не стабильная и кривая обертка вокруг сервисом выделяющих память, не вижу смысла её применять.
     
  16. icent

    icent New Member

    Публикаций:
    0
    Регистрация:
    23 апр 2009
    Сообщения:
    154
    Да, я понал. (я уж на студию погрешил было)
     
  17. SashaTalakin

    SashaTalakin New Member

    Публикаций:
    0
    Регистрация:
    15 дек 2008
    Сообщения:
    261
    у тебя голова нестабильная и кривая.

    icent
    TSS прав почти 100% ошибка в read_import_descriptor().

    Эксцепшн произойдет при попытке освобождения испорченной кучи. Может еще в других случаях - это надо конкретно смотреть как реализована куча в конкретной системе. В разных по-разному очень.
     
  18. icent

    icent New Member

    Публикаций:
    0
    Регистрация:
    23 апр 2009
    Сообщения:
    154
    Завтра заноплю вызов read_import_descriptor() и посмотрим что будет. Вообще-то хип юзается самой виндой.. так что код все-же перепроверю.
     
  19. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    SashaTalakin
    Это не тебе малыш судить. Зачем вобще хип нужен тут ?
     
  20. icent

    icent New Member

    Публикаций:
    0
    Регистрация:
    23 апр 2009
    Сообщения:
    154
    HeapAlloc честно расширяла память на столько, насколько могла :) Ее не в чем винить (ошибка была в коде read_import_descriptor), так что надстройки кернел32 не виноваты.

    [​IMG]

    TSS, SashaTalakin, Clerk, спасибо.


    p.s. Aqilla, все, что в теге code не проверяется на мат? x)