Форум: "Прочее";
Текущий архив: 2009.03.01;
Скачать: [xml.tar.bz2];
ВнизКак предотвращать Out of memory при SetLength? Найти похожие ветки
← →
Хост (2008-12-29 05:23) [0]Когда массиву задаёшь слишком большие размеры, то не редко появляется такое сообщение. Нет ли какой-нибудь функции, чтобы заранее проверять есть достаточно памяти или нет?
← →
Джо © (2008-12-29 07:00) [1]try/except с проверкой на EOutOfMemory.
← →
Хост (2008-12-29 07:34) [2]
> Джо © (29.12.08 07:00) [1]
>
> try/except с проверкой на EOutOfMemory.
А как без try/except?
После try/except происходит выход из всех функций.
← →
sniknik © (2008-12-29 08:05) [3]> А как без try/except?
никак. это единственный надежный способ.
> После try/except происходит выход из всех функций.
не происходит. см. 17ю строку.
← →
Рамиль © (2008-12-29 09:04) [4]Это же сколько надо запросить, что бы получить EOutOfMemory?
← →
test (2008-12-29 09:07) [5]Хост (29.12.08 07:34) [2]
try
.......
//какой то код
.......
except
on EOutOfMemory do ShowMessage("Не хватает памяти");
ShowMessage("Другие исключения");
end;
Может в таком случае попробовать двунаправленный связанный список?
← →
Хост (2008-12-29 10:49) [6]
> test (29.12.08 09:07) [5]
>
> Хост (29.12.08 07:34) [2]
> try
> .......
> //какой то код
> .......
> except
> on EOutOfMemory do ShowMessage("Не хватает памяти");
> ShowMessage("Другие исключения");
> end;
>
> Может в таком случае попробовать двунаправленный связанный
> список?
Попробую. А нельзя как-нибудь чтобы мне сказали, что есть максимум столько-то памяти. Чтобы не перебирать все возможные значения.
> Рамиль © (29.12.08 09:04) [4]
>
> Это же сколько надо запросить, что бы получить EOutOfMemory?
>
В памяти программа занимает 1500 что ли мегабайт. Хотя предел - в районе трёх гигов. Так, что не понимаю, чего ей там не хватает. Наверное просто какое-то неправильное распределение памяти.
← →
Jeer © (2008-12-29 10:59) [7]
> В памяти программа занимает 1500 что ли мегабайт.
Видео напихал, наверное.
← →
Slym © (2008-12-29 11:16) [8]Jeer © (29.12.08 10:59) [7]
расчет траекторий разлета частиц в БАКе с точностью 1/10000 периода полураспада бозона Хигса
← →
Anatoly Podgoretsky © (2008-12-29 11:32) [9]> Хост (29.12.2008 5:23:00) [0]
Ну и какая разница? Чем текущая не устраивает?
← →
Anatoly Podgoretsky © (2008-12-29 11:35) [10]> Хост (29.12.2008 10:49:06) [6]
Ты в курсе, что ограничение 2 гб?
← →
Правильный$Вася (2008-12-29 12:14) [11]не делать полимультимногократно SetLength
выставить максимальный размер сразу
← →
test (2008-12-29 12:18) [12]Правильный$Вася (29.12.08 12:14) [11]
Тогда можно вообще массив обычный создать.
← →
asail (2008-12-29 12:36) [13]
> Может в таком случае попробовать двунаправленный связанный
> список?
Памяти жрать есче больше будет (8 байт на указатели для каждого элемента). А, если у него там 1.5 гига массив из интежеров, например, то ваще каюк.
К тому-же если нужен прямой доступ к любому элементу массива, то при таком кол-ве элементов - каюк в квадрате.
← →
StriderMan (2008-12-29 12:36) [14]храните сразу на диске. все равно в своп все свалится. (если конечно не на серьезном сервере запускать)
← →
asail (2008-12-29 12:40) [15]
> В памяти программа занимает 1500 что ли мегабайт. Хотя предел - в районе трёх гигов. Так, что не понимаю, чего ей там не хватает.
Насколько я в курсе, при SetLength, ищется НЕПРЕРЫВНЫЙ свободный участок памяти нужного объема... В случае сильной фрагментации его может и не оказаться.
← →
Правильный$Вася (2008-12-29 13:06) [16]
> Тогда можно вообще массив обычный создать.
если время жизни данных в массиве равно времени жизни программы, то да
если же массив нужен ненадолго, то лучше не надо обычного
← →
Servy © (2008-12-29 14:38) [17]> В памяти программа занимает 1500 что ли мегабайт. Хотя предел
> - в районе трёх гигов.
Предел в районе двух гигов. Чтобы сделать предел в районе трех гигов, необходима Win XP и выше, в boot.ini поставить параметр /3Gb и в PE заголовке твоего exe файла поставить отметку о том, что программа поддерживает больше двух гигабайт памяти. Подробности в гугле.
← →
Jeer © (2008-12-29 16:55) [18]
> Предел в районе двух гигов. Чтобы сделать предел в районе
> трех гигов, необходима Win XP и выше,
Я тебя уверяю, что даже Windows NT ent.srv. имел возможность работы с памятью объемом до 3 Gb. Не говоря уж о W2k adv.srv, который имеет возможность использования механизма PAE для доступа к объему выше 4Gb
Пример для w3:
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(2)\WINDOWS="Windows Server 2003, Enterprise" /fastdetect /PAE
← →
Anatoly Podgoretsky © (2008-12-29 17:01) [19]> Jeer (29.12.2008 16:55:18) [18]
Без разницы, Дельфи просто не использует свыше 2 гб, как только это случается происходит Out of memory
← →
Правильный$Вася (2008-12-29 17:03) [20]
> даже Windows NT ent.srv. имел возможность работы с памятью
> объемом до 3 Gb. Не говоря уж о W2k adv.srv
серверные операционки устроены несколько иначе в этом плане
← →
Jeer © (2008-12-29 17:03) [21]
> Без разницы, Дельфи просто не использует свыше 2 гб,
Использовать DLL на Си :)
или по Корану запрещено ?
← →
Jeer © (2008-12-29 17:08) [22]
> Правильный$Вася (29.12.08 17:03) [20]
Между прочим, XP SP2 не поддерживает механизм PAE в отличии от SP1 :))
← →
Рамиль © (2008-12-29 17:13) [23]
> Между прочим, XP SP2 не поддерживает механизм PAE в отличии
> от SP1 :))
Не то что бы не поддерживает. Поддерживает, но требует указания в boot.ini ;)
← →
Jeer © (2008-12-29 17:18) [24]Причина
Эта проблема возникает из-за изменения в Windows XP с пакетом обновления 2 (SP2), которое также содержится и в Windows Vista. В режиме PAE для улучшения совместимости драйверов были сделаны изменения. Для устранения проблем совместимости в Windows XP с пакетом обновления 2 (SP2) внесены изменения в слой абстрагирования оборудования (HAL), имитирующие поведение 32-разрядного прямого доступа к памяти слоя HAL. При этом в режиме РАЕ измененный HAL выделяет неограниченное число регистров отображения, а диспетчер памяти ядра игнорирует физические адреса за пределами диапазона 4 ГБ. Любая системная оперативная память, размер которой превышает 4 ГБ, не сможет быть адресована Windows и использована системой. Из-за ограничения адресного пространства до 4 ГБ устройства с 32-разрядной шиной прямого доступа к памяти не будут распознавать транзакции с адресами, лежащими за пределами 4 ГБ. Так как эти изменения ликвидируют необходимость в транзакциях с двойной буферизацией, они помогают исключить появление целого класса ошибок, относящихся к правильности реализации двойной буферизации в некоторых драйверах.
Основная проблема совместимости драйверов связана с использованием режима РАЕ в 32-разрядных системах. Режим PAE позволяет процессору адресовать более чем 4 ГБ памяти. Основное отличие между схемами разбиения памяти на страницы в PAE и не в PAE заключается в дополнительном уровне разделения, необходимом в режиме PAE. В режиме PAE требуются три уровня разбиения памяти на страницы вместо двух.
Если включен режим расширения физических адресов, некоторые драйверы не загружаются, поскольку устройство не поддерживает 64-разрядную адресацию или драйвер полагает, что режим расширения физических адресов требует более 4 ГБ оперативной памяти. Такой драйвер исходит из того, что в режиме расширения физических адресов будут поступать только 64-разрядные адреса, которые он (или соответствующее устройство) не в состоянии обрабатывать.
Другие драйверы загружаются в режиме РАЕ, но нарушают стабильность системы, пытаясь напрямую изменять записи в системной таблице страниц (PTE). В режиме РАЕ такие драйверы вместо ожидаемых 32-разрядных записей получают 64-разрядные записи таблицы страниц.
Наибольшая трудность связана с прямым доступом к памяти (DMA) и выделением реестров отображения. Многие устройства, которые поддерживают прямой доступ к памяти (как правило, 32-разрядные адаптеры), не могут выполнять 64-разрядную физическую адресацию. Если устройство запущено в 32-разрядном режиме, ему доступен весь диапазон физических адресов. В режиме расширения физических адресов данные могут располагаться по физическим адресам за пределами диапазона в 4 ГБ. Для включения устройств с этими ограничениями, семейство Windows 2000 Server и более поздние версии Windows снабжены системой двойной буферизации транзакций DMA. Семейство Windows 2000 Server и более поздние версии Windows осуществляют это с помощью передачи 32-битного адреса, указанного в регистре отображения. Устройство выполняет операцию DMA с 32-разрядным адресом, а ядро копирует память по 64-разрядному адресу, который выделен драйверу. Если режим РАЕ выключен, драйверам 32-разрядных устройств не требуется поддержка регистров отображения со стороны реальной памяти, т. е. двойная буферизация не нужна, поскольку все устройства и драйверы располагаются в 32-разрядном диапазоне адресов. В результате тестирования драйверов 32-разрядных устройств на компьютерах с 64-битной архитектурой процессоров выяснилось, что большинство драйверов с поддержкой прямого доступа к памяти используют неограниченные регистры отображения.
← →
Хост (2008-12-30 01:27) [25]
> Servy © (29.12.08 14:38) [17]
>
> > В памяти программа занимает 1500 что ли мегабайт. Хотя
> предел
> > - в районе трёх гигов.
>
> Предел в районе двух гигов. Чтобы сделать предел в районе
> трех гигов, необходима Win XP и выше, в boot.ini поставить
> параметр /3Gb и в PE заголовке твоего exe файла поставить
> отметку о том, что программа поддерживает больше двух гигабайт
> памяти. Подробности в гугле.
Пишут, что это не помогает: http://www.ixbt.com/soft/windows-4gb.shtml
← →
Servy © (2008-12-30 01:35) [26]> Пишут, что это не помогает: http://www.ixbt.com/soft/windows-
> 4gb.shtml
Вы видимо или не дочитали, или не в теме:
Время от времени можно увидеть совет по увеличению памяти, доступной системе: добавить в файл boot.ini параметр /3GB. На самом деле этот совет, как говорится, не из той оперы. Этот параметр обеспечивает перераспределение виртуального адресного пространства приложений между ними и системой, но никак не влияет на работу с физической памятью.
Вам был данный совет был дан как раз для того, чтобы вашей программе было доступна 3 Гб виртуальной памяти, а не физической. Out of memory возникает, если программе не хватает виртуальной памяти (если не хватает физической, просто начнется своппинг). В чем разница между физической и виртуальной памятью написано во многих источниках, гугл в помощь.
ЗЫ Сам писал программу, которая выкушивала 2,8 гигабайта памяти :).
← →
Хост (2008-12-30 01:48) [27]
> Servy © (30.12.08 01:35) [26]
> (если не хватает физической, просто начнется своппинг)
Тогда похоже вы сами не прочитали статью.
Там как раз о том, что никаким свопингом нельзя получить больше памяти.
← →
Servy © (2008-12-30 03:38) [28]> Тогда похоже вы сами не прочитали статью.
> Там как раз о том, что никаким свопингом нельзя получить
> больше памяти.
Процитируйте, пожалуйста, где там говорится о том, что программе нельзя выделить ~3 Гб виртуальной памяти (имея меньший объем ОЗУ). Я полагаю, что такого там не написано (потому что это неправда).
Статья о том, что 32битные версии Windows не могут полноценно работать с 4 гигабайтами ОЗУ, потому как часть адресов заблокирована внешними устройствами, и система видит лишь около 3 Гб физической памяти. Какое отношение сей прискорбный факт имеет к выделяемой вашей программе виртуальной памяти остается загадкой.
Необходимость ключа /3Gb и установленного бита в PE заголовке очень проста: нижние (младшие) 2 гигабайта виртуального адресного пространства выделяются приложению для своих нужд, верхние 2 гигабайта оставляют системе. Начиная где-то с Win2000 Microsoft догадался, что 2гб пользовательским программам может быть и маловато, и заметил, что системные функции можно впихнуть и в 1 гигабайт. Однако, выделение более 2х гигабайт виртуальной памяти приводило к краху некоторых программ - программисты привыкли, что старший бит указателя всегда равен 0, и использовали этот бит для своих нужд, что приводило к неправильной работе, если программе выделялось память с адресом выше $7FFFFFFF. Поэтому, чтобы обеспечить работоспособность таких программ, был введен указанный ключ и бит в PE заголовке, которые позволяют убедить Windows, что ваша программа не использует старший бит в указателе для своих нужд и соответственно может спокойно работать с тремя гигабайтами виртуальной памяти.
Еще раз, советую вам ознакомиться с концепцией виртуальной памяти, например, здесь:
http://ru.wikipedia.org/wiki/Виртуальная_память
и уяснить, что память, которая выделяется вами с помощью SetLength является виртуальной памятью, и адрес любой переменной или процедуры, получаемый вашей программой, является виртуальным адресом, а не адресом в физической памяти.
> [18] Jeer ©
Прошу прощения, достоверно я знал о том, что ~3 Гб памяти путем упомянутых махинаций можно выделить в WinXP и выше. Я не отрицаю тот факт, что флаг /3Gb может поддерживаться и в более ранних системах. Правда, к чему пассы в сторону PAE мне непонятно, учитывая что прикладной программе выделяется виртуальная память. Ключа /3Gb в вашем конфиге нет, а значит одно приложение не сможет выделить более примерно 2х гигабайт виртуальной памяти (разумеется, это не помешает системе воспользоваться всем доступным ей объемом ОЗУ в случае запуска более чем одного memory consuming приложения).
> [0]
> Когда массиву задаёшь слишком большие размеры, то не редко
> появляется такое сообщение. Нет ли какой-нибудь функции,
> чтобы заранее проверять есть достаточно памяти или нет?
Такой функции нет по той причине, что в большинстве случаев, если программа говорит выделить ей некоторое количество памяти, значит для ее работы _необходимо_ указанное количество памяти, и невозможность выделения означает ошибку. Случай, когда программа может обойтись и половиной указанного количества памяти достаточно редок (это подразумевает алгоритм, который может работать как если ему выделена память полностью в запрощенном объеме, так и лишь частично; такие алгоритмы встречаются нечасто).
Если вам хочеться именно определить, можно ли выделить указанное количество памяти, или нет, это сделать очень просто, о чем и написано в [1]. Если вы не знаете что такое try except, или не понимаете как он работает, к вашим услугам хелп. Написать процедуру выделения максимального доступного объема тоже не сложно, try except для отлавливания факта неудачи выделения и бинарный поиск.
← →
han_malign © (2008-12-30 12:00) [29]
> > Нет ли какой-нибудь функции, чтобы заранее проверять есть достаточно памяти или нет?
> Такой функции нет
- функция то есть, только для ее использования надо приложить некоторые усилия...
VirtualQuery
для получения карты использования виртуальной памяти надо максимум 2Гб/64Кб = 65536 итераций - поиск свободного диапазона адресов максимальной длинны вполне тривиальная задача, но не для частого использования, с возможными граблями в многопоточном варианте, и возможным крахом менеджера памяти("DelphiMM") при резервировании этого диапазона(VirtalAlloc) ...
> try except для отлавливания факта неудачи
p:=SysGetMem(sz); p <> nil
seh-офилы, блин...
← →
Servy © (2008-12-30 13:10) [30]> > Такой функции нет
>
> - функция то есть, только для ее использования надо приложить
> некоторые усилия...
Имелось в виду:
Готовой такой функции нет, однако, ее можно написать, о чем и говорилось в следующем абзаце.
> > try except для отлавливания факта неудачи
>
> p:=SysGetMem(sz); p <> nil
> seh-офилы, блин...
*Servy сжег все книги, расхваливающие seh и посыпал голову пеплом*
А если серьезно, то могу попытаться отмазаться тем, что строке (или дин. массиву), которому автор делает SetLength нужно еще около дюжины байт для служебных данных длины, кол-ва ссылок и т.п.), причем кол-во этих даннных может отличаться в разных версиях делфи. То есть, если мы можем выделить 3000 байт памяти, это еще не означает, что мы можем установить длину некой строки в 3000. Соответственно, нужно учитывать этот запас, который от версии к версии может поменяться. Вариант с try except имеет в этом плане преимущество, хотя выполняется очевидно несколько медленнее.
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2009.03.01;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.005 c