2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 проблемы с выделением памяти
Сообщение05.09.2024, 16:30 


15/12/22
182
При попытке выделить большой кусок памяти, функции malloc() и realloc() возвращают ненулевой указатель,
но при записи в выделенную область данных, в какой то момент возникает ошибка сегментации. Подмечено,
что ошибки возникают при достижении объёма памяти 32 Гб, хотя доступно 64 Гб. Т.е. если выделяется менее 32 Гб,
то программа отрабатывает нормально. Но если требуется выделить больше, например 45 Гб, то возникают вышеописанные ошибки сегментации. Функция info.freeram прямо перед началом выделения памяти, показывает, что доступной памяти достаточно.
В чём может быть проблема?

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение05.09.2024, 21:07 
Заслуженный участник


18/09/21
1756
Проверьте, нет ли где непреднамеренных преобразований типов целого или указателя для самого размера и для полученного указателя.
(Вообще, хорошо бы в теме указать, что за платформа используется и компилятор.)

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение05.09.2024, 22:30 


15/12/22
182
gcc под linux
проверял, думал uint8_t занимает 2 байта, но sizeof(uint8_t) выдаёт 1.
В диспетчере задач тоже видно, что сбой происходит при увеличении объёма занятой памяти до 32 Гб, странное какое то совпадение.
В самой системе $ free выдаёт total, free, available примерно 64 Гб, ну и прямо перед выделением памяти через info.freeram определяется примерно 64 Гб, никаких выделений после этого не делается, только копирование, сначала даже всё работает, но как доходит до 32Гб, вылетает ошибка сегментирования

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение05.09.2024, 22:45 
Заслуженный участник


07/08/23
1084
А sizeof(char*) точно равен 8?

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение05.09.2024, 23:08 


27/08/16
10195
Напишите простой тест, возможно, локализующий вашу проблему. Выделите массив uint8_t заданного константой размера, и заполните его последовательно в цикле хоть нулями. Больше эта программа не должна делать ничего.

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение05.09.2024, 23:33 


15/12/22
182
realeugene в сообщении #1653421 писал(а):
А sizeof(char*) точно равен 8?

именно так

realeugene в сообщении #1653421 писал(а):
Напишите простой тест, возможно, локализующий вашу проблему

этот тест работает отлично, заполняются все 64 Гб

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение05.09.2024, 23:50 
Заслуженный участник
Аватара пользователя


28/07/09
1238
Missir в сообщении #1653422 писал(а):
этот тест работает отлично, заполняются все 64 Гб

а считываются ли? вместо нулей заполнить 1.0f, в отдельном цикле считать и вывести сумму.

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение06.09.2024, 00:27 


15/12/22
182
Legioner93 в сообщении #1653424 писал(а):
а считываются ли?

я писал не нули, а i/1000000000 (чтобы помещалось в uint8) последний байт считался нормально

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение06.09.2024, 01:22 


27/08/16
10195
Missir в сообщении #1653422 писал(а):
этот тест работает отлично, заполняются все 64 Гб
Скорее всего, у вас на самом деле из-за ошибки в вашем коде происходит обращение по неправильному адресу. Например, вы индексируете 32-битным целым массив двойных плавающих чисел. Или массив указателей.

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение06.09.2024, 02:34 


15/12/22
182
realeugene в сообщении #1653428 писал(а):
Скорее всего, у вас на самом деле из-за ошибки в вашем коде происходит обращение по неправильному адресу

действительно, была ошибка, при определённых условиях он зацикливался, и писал до бесконечности, то что 32 Гб, это случайное совпадение. Исправил, сейчас обрабатывает эти данные без ошибок. Память используется вся. Всем большое спасибо

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение07.09.2024, 23:33 
Аватара пользователя


28/10/21
100
Missir в сообщении #1653363 писал(а):
При попытке выделить большой кусок памяти, функции malloc() и realloc() возвращают ненулевой указатель,
но при записи в выделенную область данных, в какой то момент возникает ошибка сегментации.


Ну вообще-то вы описываете классические симптомы поведения виртуальной памяти в системе с разрешенным overcommit.

То есть при выделении памяти никакого физического выделения не происходит, а происходит лишь резервирование соответствующего диапазона адресов в адресном пространстве процесса. Никаких физических ресурсов за этими адресами изначально не стоит. То есть вам изначально выделяют "воображаемую" память. Вы получаете не память, а лишь диапазон адресов.

Выделение физических ресурсов, т.е. сопоставление вашему диапазону адресов настоящих физических страниц в ОЗУ и/или в своп-файле, начнется только тогда, когда вы начнете физически записывать в эту память данные. Оно будет делаться постранично (по 4 кб) по мере необходимости. И если в какой-то момент окажется, что физических ресурсов недостаточно, вы получите ошибку при записи в как будто уже выделенную "вашу" память.

То есть выделение памяти в такой системе - это не более чем вялое обещание, что память "может быть найдется", когда вы действительно начнете с ней работать. А в реальности она может и не найтись...

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение08.09.2024, 00:11 
Заслуженный участник
Аватара пользователя


28/07/09
1238
TheRuinedMap

TheRuinedMap в сообщении #1653694 писал(а):
. А в реальности она может и не найтись...


...и прислать SIGKILL. Тогда как в условии SIGSEGV. Вы невнимательны к симптомам, коллега.

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение08.09.2024, 13:38 


15/12/22
182
Вообще, там не всё так однозначно, если проверить доступную память после и до выделения с помощью info.freeram ,
то результат не меняется, но меняется после того как в выделенную память начнут записываться данные. Это наверное тоже может привести к проблемам

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение08.09.2024, 14:59 
Заслуженный участник


20/08/14
11761
Россия, Москва
Missir
Это не проблема, а особенность работы ОС с памятью. Выделяйте с флагом инициализации (или инициализируйте сами если в API флага не предусмотрено), будет дольше, зато память реально выделится. А без него память не выделяется, а резервируется, без физического выделения, которое происходит только по мере записи в страницы (и переносит тормоза из начала во внутренние циклы, размазывая и по ним, и по времени работы, которое суммарно увеличивается незначительно (но бывают и исключения), лишь перераспределяется между кусками кода). ОС любит экономить физическую память и это один из её механизмов.
Особенно это хорошо видно на примере выделения большого куска памяти в локальном стеке, не просто sub RSP,d, а потом ещё и пишут туда с шагом 4K неважно что, иначе ОС реально физическую память не выделит.
Собственно TheRuinedMap объяснил ровно это же самое.
Насколько это применимо к конкретной версии линукса я не в курсе.
Видимо Вам пришла пора почитать что-то более глубокое о работе своей ОС, раз стали (не в первый раз) натыкаться на особенности её работы и принимать это за глюки/проблемы.

 Профиль  
                  
 
 Re: проблемы с выделением памяти
Сообщение13.10.2024, 16:12 
Аватара пользователя


07/02/12
1433
Питер
Эта особенность связанна с работой со свопом, когда его размер определяется системой. В случае, когда своп близок к завершению, система его предупреждающе увеличивает, но этот процесс условно асинхронный относительно вызовов приложений по выделению памяти - соответственно, иногда система может не успевать, и выделение памяти может фейлиться.

Ошибка у вас возникает при обращении к памяти, а не при ее как вам кажется выделении, т.к. реальное выделение памяти (commit), происходит при обращении к выделенному (reserved) адресному пр-ву. При выделении маленьких блоков это не проявляется, т.к. внутри вашего приложения между malloc и системой еще есть прилинкованный посредник - менеджер памяти - он выделяет и память у системы большими блоками и нарезает внутри приложения на маленькие. Что бы этого избежать, можно использовать более низкоуровневое ОС-зависимое API, чем malloc/release. В случае Windows это VirtualAlloc/Protect/Free. В случае Linux - это mmap/madvise/mprotect. Или костыль, как написали выше - после выделения пробежаться с шагом 4K (одной страницы) по выделенной памяти и наследить (это неэффективно с точки зрения использования физической памяти, но значительно проще).

Сама проблема лечится фиксированием минимального размера свопа, поставьте x2 от размера ОЗУ. Также лечится использованием вышеупомянутых ОС-зависимых API, но в цикле (например, пытаться выделять reserve+commit память 10 раз с периодом в 100 мс, а потом уже осознанно падать с занесением в журналы) - тоже костыль, но работает хорошо.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 15 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: Felon1412c


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group