|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Авг 16, 2003 04:48:51 Каков этот размер под Win32? Я хочу записывать туда массивы до сотен килобайт. Насколько это безопасно, чтобы не вызвать Stack Overflow? Или дурью не париться и использовать GlobalAlloc? А то я даже слышал утверждения, что стек под Win32 можно считать безразмерным. |
|
|
Дата: Авг 16, 2003 05:06:09 На мой взгляд лучше пользоваться GlobalAlloc/HeapAlloc, причём предпочтительней второе. Стек не может быть безразмерным т.к. он растёт вниз (это моё мнение). |
|
|
Дата: Авг 16, 2003 06:04:34 SolidCode А то я даже слышал утверждения, что стек под Win32 можно считать безразмерным. Не верьте в это! Stack Overflow -- явление редкое (особенно на NT), но бояться его имеет смысл. Я тут на 9x попытался рекурсивно вызвать одну функцию и... пожалел. |
|
|
Дата: Авг 16, 2003 10:13:38 · Поправил: bsl_zcs Размер и поведение стека определяется парой полей в PE-header'е: Stack Commit Size - количество памяти, выделяемой под стек сразу при загрузке, и Stack Reserve Size - размер, до которого стек может дорасти. Устанавливаются они штатно при линковке. Ключи линкерам можно посмотреть в доке. Нештатно - любым PE-редактором, либо хекс-редактором по смещениям 64h и 60h соответственно. |
|
|
Дата: Авг 16, 2003 12:33:47 · Поправил: Four-F [ SolidCode: ...Я хочу записывать туда массивы до сотен килобайт. Насколько это безопасно... ] Память для стека выделяется динамически. Изначально она зарезервирована и выделено только две верхние страницы. Верхняя доступна для записи, а следующая ниже, под NT помечена флагом PAGE_GUARD, а под маздаем, вроде, PAGE_READONLY. Когда esp двигается вниз и дойдет до сторожевой страницы происходит исключение и соответствующий обработчик выделяет еще одну страницу ниже и помечает ее PAGE_GUARD/PAGE_READONLY, а ту что была PAGE_GUARD/PAGE_READONLY делает доступной для записи. Так оно и продолжается до тех пор пока не исчерпается зарезервированная память. Но если ты попытаешься перепрыгнуть сторожевую страницу и запишешь что-то в зарезервированую область, то это исключение будет обработано по другому - процесс просто исчезнет. Если ты собираешься пихать на стек "массивы до сотен килобайт", то такое запросто может произойти если на асме пишешь. Если на ЯВУ, то компилятор добавляет дополнительный код, который не позволяет перепрыгнуть сторожевую страницу, а начинает сдвигать ее вниз производя к ней обращения, до тех пор пока стек не увеличится до нужного размера. |
|
|
Дата: Авг 16, 2003 14:13:33 Согласен с Four-F, от себя могу добавить ещё совет - почитать Рихетера , раздел о выделении памяти - там о стеке все доступно описано, а так же есть пример использования подобной технологии для создания динамических массивов, с выделением памяти "on demand" |
|
|
Дата: Авг 18, 2003 07:56:02 Спасибо всем, кто откликнулся. Много различных путей решения. Есть из чего выбирать. rst, не подкинешь ссылочку на Рихетера? |
|
|
Дата: Авг 18, 2003 11:06:38 SolidCode Кстати подобное писал я в Записках Дзенствующего. Смотри там. |
|
|
Дата: Авг 18, 2003 11:13:42 SolidCode Заглядывай сюда периодически - как сделают-таки раздел с моими книгами - тогда и возьмешь его. А я сегодня пока его залью на этот стервер. |
|
|
Дата: Авг 18, 2003 13:18:02 SolidCode, возможно будет интересно: Как подменить стек? А Рихтер тут: http://anatolix.naumen.ru/win32books.htm |
|
|
Дата: Авг 18, 2003 13:59:29 Ощущаю себя таким занудой... Но всё-таки Four-Fпоправлю. ;) Рост стека описан правильно, только изначально выделяются не две верхние страницы, а тот самый Stack Commit Size. Проверяется элементарно - пишется что-нибудь вроде lea eax,[esp-600000h]
mov dword [eax], 'Ok' ; 6B4Fh
push 0
push eax
push eax
push 0
call [MessageBox]
retПосле чего, это собирается с различными параметрами в PE-зголовке и запускается. При указании Stack Commit Size должного размера (в этом примере >600000h) оно прекрасно запускается и работает.
Судя по всему, commit size имеет приоритет перед reserve size. То есть, если указать reserve меньше чем commit, всё работает и не ругается. Во всяком случае, на 98 и 2k. 2 SolidCode: Надеюсь, тебе это нужно именно для динамических массивов? Если для статических, то их можно вообще по-простому объявить в секции неинициализированных данных. Любого разумного размера. И обращаться к ним можно будет прямо по адресу... |
|
|
Дата: Авг 18, 2003 14:48:21 · Поправил: Four-F Ну, раз пошла такая пьянка... Я исходил из того, что прога собирается со стандартными параметрами стека. bsl_zcs, согласись, что выделять для стека >600000h просто потому, что кому-то хочется разместить в нем массив, непонятно зачем - это изврат полный, хотя конечно можно и так. [ bsl_zcs: только изначально выделяются не две верхние страницы, а тот самый Stack Commit Size. ] Я не буду утверждать этого на 100%, только на 99,99% ;-), но выделяется Stack Commit Size + еще одна страница с флагом PAGE_GUARD (под NT). Т.е. если прога собрана со стандартными параметрами стека, изначально выделится как раз две страницы. Кстати, размер выделяемого стека можно еще задать при создании потока CreateThread. |
|
|
Дата: Авг 25, 2003 13:07:22 Ещё вопрос. Чем HeapAlloc лучше (если лучше) GlobalAlloc? |
|
|
Дата: Авг 25, 2003 13:16:08 GlobalAlloc устарела и оставлена для обратной совместимости. |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.100 |