GlobalAlloc мож узнать заранее, сколько можно реально взять памяти?

Тема в разделе "WASM.BEGINNERS", создана пользователем TOLSTOPUZ, 14 май 2008.

  1. TOLSTOPUZ

    TOLSTOPUZ New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2008
    Сообщения:
    509
    Хочу к примеру взять кусок памяти. Можно ли заранее узнать, сколько максимальноо можно брать, чтобы не было ошибки?
     
  2. DEEP

    DEEP Андрей

    Публикаций:
    0
    Регистрация:
    27 апр 2008
    Сообщения:
    491
    Адрес:
    г. Владимир
    Размер, который необходим, сильно зависит от конкретной ситуации.
     
  3. TOLSTOPUZ

    TOLSTOPUZ New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2008
    Сообщения:
    509
    Простите, а разве GlobalAlloc не ограничен оперативной памятью?
     
  4. TOLSTOPUZ

    TOLSTOPUZ New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2008
    Сообщения:
    509
    Да это понятно. Я и спрашиваю, можно ли как-то узнать, сколько я могу получить, прежде чем вызывать GlobalAlloc
     
  5. DEEP

    DEEP Андрей

    Публикаций:
    0
    Регистрация:
    27 апр 2008
    Сообщения:
    491
    Адрес:
    г. Владимир
    Ну если уж на то пошло, то, согласно "плоской" модели памяти, проге может быть выделено до 2 ГБ (минус образ проги) виртуальной памяти, вне зависимости от размера физической RAM. Верхние 2 ГБ (по крайней мере в 98-м, с которым пока что необходимо, имхо, обеспечивать совместимость) система забирает себе.
     
  6. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Возьми, скажем, 2 ГБ. Если не возьмётся - уменьши количество беруемой памяти в два раза и попробуй ещё раз. И так далее. Совсем немного попыток понадобится.
     
  7. TOLSTOPUZ

    TOLSTOPUZ New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2008
    Сообщения:
    509
    Да так-то конечно можно...
    Просто как-то... непрофессионально...
    Ну если нет Апишки такой - ладно...
     
  8. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Собственно GlobalAlloc выделяет память из кучи. И зависит сколько памяти выделилось для процессной кучи. Обычно это не так много.
     
  9. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    n0name
    Во-первых, главная куча процесса является растущей (приращение идет сегментами по 1Мб). Во-вторых, блоки размером более 512К по любому выделяются не непосредственно в "общей куче", а "индивидуально" через VirtualAlloc и в куче сохраняются только ссылки (дескрипторы) на эти блоки

    TOLSTOPUZ
    Память в винде является виртуальной, поэтому (при достаточном свободном месте на диске) выделение блока ограничено только наличием подходящей "дыры" незанятых виртуальных адресов. Для поиска "дыры" нужно пробежаться по списку занятых адресов, что собственно и делает VirtualAlloc - если находит, то сразу и резервирует\выделяет. А бегать по списку только ради спортивного интереса без выделения памяти смысла нет, поэтому и апишки такой нет
     
  10. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    по теме: GlobalMemoryStatus - от неё можно плясать.
    + фрагментированность АП, как уже сказали, не даст заполучить всю доступную вирт.память в один заход одним куском.
     
  11. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Угу. забыл про то что она growable.
    а разве не на ALIGN_UP(Size + sizeof(HEAP_HEADER), 16) ?
    Вот в это почему то не верю. Можешь ткнуть носом в дизасм листинг, сам я что-то не вижу...
     
  12. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Я имел ввиду не выделение блока внутри кучи, а о резервировании адресов под новый сегмент (HEAP.SegmentReserve = hHeap+18h = 1Мб по дефолту)

    В листинге без стакана не разберешься, поэтому лучше глянь в руководство по SoftIce и в структуры HEAP_ENTRY и HEAP
    Размер блока кучи измеряется в 8 байтных единицах и хранится в заголовке HEAP_ENTRY в виде ushort Size, отсюда и предельный размер бока, выделяемого в самой куче = 64К*8 = 512К. Реально предел берется чуть меньше (0FE00h*8 = 7F000h) и хранится в хидере самой кучи HEAP.VirtualMemoryThreshold (hHeap+14h). Ссылки на выделенные виртуальные блоки хранятся в списке Heap.VirtualAllocdBlocks (hHeap+50h)

    Что касается листинга, то в XP SP2 проверка на предельный размер выглядит так
    Код (Text):
    1. ;ntdll.RtlAllocateHeap
    2. 7C9116BF    3B7B 14         CMP     EDI,[EBX+14]  ;edi = (size+7) shr 3, ebx = hHeap
    3. 7C9116C2  ^ 0F86 F0FCFFFF   JBE     ntdll.7C9113B8
    Дальше по джампу дебри непролазные (по кр.мере на первый взгляд), копаться в которых у меня желания не было и нет :)
     
  13. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    leo
    а, ты про RtlAllocateHeap, я думал ты про GlobalAlloc говорли ибо ""индивидуально" через VirtualAlloc и в куче сохраняются только ссылки (дескрипторы) на эти блоки" думал что относится к однйо функции. В RtlAllocateHeap вполне возможно. Там кода - без поллитры не разобратся %)
     
  14. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    n0name
    Я ж сказал "по любому выделяются", имея в виду, что GlobalAlloc в плане выделения памяти ничем не отличается от HeapAlloc -> RtlAllocateHeap. При GMEM_FIXED вообще сразу переходит на HeapAlloc, а для GMEM_MOVEABLE только доп.запись дискриптора в свой табличке создает и все. Поэтому и смысла в ней никакого нет, только для клипборда и дде для совместимости
     
  15. TOLSTOPUZ

    TOLSTOPUZ New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2008
    Сообщения:
    509
    Значит, практически с помощью кода можно получить максимально возможную квоту вплоть до 1 байта? Можно?
    И если да, то тогда насколько статичен будет этот полученный размер? Например, возьмёт и изменится, добавит пару байт... Вот в чём вопрос?
     
  16. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Какая пара байт ?! Если речь о 512К и более, то рулит VirtualAlloc с дискретом резервирования адресов = 64К

    ???
    Насколько в проге (в экзешнике и всех длл) не будет явных или скрытых выделений или освобождений динамической памяти (включая Create\ExitThread, Load\FreeLibrary и т.п.)
     
  17. TOLSTOPUZ

    TOLSTOPUZ New Member

    Публикаций:
    0
    Регистрация:
    26 апр 2008
    Сообщения:
    509
    Короче говоря, объясню, к чему я клоню...
    можно ли рассматривать некоторые моменты оперативной памяти как структуру настолько нестабильную, что есть возможность получать из некоторых её параметров "случайное число"?
     
  18. RamMerLabs

    RamMerLabs Well-Known Member

    Публикаций:
    0
    Регистрация:
    11 сен 2006
    Сообщения:
    1.426
    просто так ты прямого доступа и оперативе не получишь. проще использовать ГСЧ.
     
  19. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    TOLSTOPUZ
    Посмотри в Олли карту памяти любого приложения : если там и есть нестабильность, то довольно закономерная. Физ. память действительно делится между приложениями, но реальные адреса запрятаны в системе и без ring0 ты туда не попадешь.
     
  20. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    USER_SHARED_DATA можно попробовать.