Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 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.007 c
15-1230522124
Slider007
2008-12-29 06:42
2009.03.01
С днем рождения ! 27 декабря 2008 суббота


2-1232345049
Ruslan777
2009-01-19 09:04
2009.03.01
Проверка нажатия кнопки во цикле?


10-1152862016
deplhi
2006-07-14 11:26
2009.03.01
property in com


15-1230572825
Alkid
2008-12-29 20:47
2009.03.01
Перфекционизм vs. тяп-ляп.


15-1230607135
Slider007
2008-12-30 06:18
2009.03.01
С днем рождения ! 30 декабря 2008 вторник





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский