LINUX.ORG.RU

Не понимаю c++ new

 


0

2

Я всегда считал, что при нехватки памяти new возвращает NULL.

Но в среде Windows-wsl-linux-Clion-c++ вместо NULL я получаю огрызок памяти, что, естественно, приводит к сбою.

Я что-то не знаю? Может быть это что-то новое в стандартах?


Во-первых, я на всякий случай напомню, что new — переопределяемая операция. У тебя в проекте она не переопределяется, случаем?

Во-вторых, посмотри в сторону std::bad_alloc.

В третьих, я не спец по clion, но насколько я помню, это IDE. А тут нужны, скорее, знания, какой у тебя компилятор и стандартная библиотека.

hobbit ★★★★★
()
Последнее исправление: hobbit (всего исправлений: 1)

В linux (и в WSL, я так понимаю, тоже) оптимистичная стратегия распределения памяти. Т.е. malloc/new всегда что-то вернёт, а вот есть-ли ФИЗИЧЕСКАЯ память - узнаем при первом к ней обращении.

SkyMaverick ★★★★★
()

Как ты умудрился не получить память с включённым оверкоммитом?

ox55ff ★★★★★
()

Во-первых, new без параметра std::nothrow при нехватке памяти не возвращает null, как минимум с С++98, а выбрасывает std::bad_alloc. А во-вторых надо смотреть в сторону vm.overcommit_memory.

Begemoth ★★★★★
()
Ответ на: комментарий от apt_install_lrzsz

Как я понял ТС, у него включен overcommit и он ничего не видит, а только segfault когда ядро не может страницу ему закоммитить, но это уже сильно позже того как new отработал

Begemoth ★★★★★
()
Ответ на: комментарий от apt_install_lrzsz

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

Siborgium ★★★★★
()

И все-таки, есть ли простой способ узнать получил я заказанную память или нет?

ezus
() автор топика

в среде Windows-wsl-linux-Clion-c++ вместо NULL я получаю огрызок памяти, что, естественно, приводит к сбою.

Приведи минимальный пример воспроизводимой проблемы.

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

Действительно, у меня есть проблема с числами, но вопрос остается.

В программе есть постоянно растущие булевские вырожения, и часто, в пределе они превышают доступную память. Мне просто надо знать, что памяти больше нет, и в этом случае выйти с соответствующим сообщением. И пользователь должен изменить входные параметры вычислений.

Раньше в Windows у меня проблем не было. Но сейчас мне надо перейти в linux.

ezus
() автор топика
Ответ на: комментарий от ezus

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

Значения? Надеюсь, ты хранишь их в битах (как std::vector<bool>), а не в байтах.

Мне просто надо знать, что памяти больше нет

Мониторь свободную память системы без учёта файловых кэшей. Как только подойдёт к 100% (95%, 90%), то завершай работу. Про swap не забудь.

ox55ff ★★★★★
()
Ответ на: комментарий от ezus

Действительно, у меня есть проблема с числами,

Нет, у тебя есть проблема, что ты не привёл ни строчки кода. Без кода ты можешь разглагольствовать на форумах до второго пришествия.

LamerOk ★★★★★
()

Windows-wsl-linux-Clion-c++

Забыл спросить. wsl второй версии или первой? wsl2 полноценный линукс с ядром в виртуалке. wsl1 (уже устарел) всего лишь прокладка между linux окружением и winapi и там могут быть всякие странности.

ox55ff ★★★★★
()
Ответ на: комментарий от LamerOk
	ZSTRY  //try 
	{
		allsz += _szUPool;
		_pool = new TBitUnit[_szUPool];		
	}
	#ifdef ZSCATCH
 	catch(...)
	{
		_pool= NULL;
		string msg = "Error: No free memory for new pool ";
		gMsgr.newMsg(ZEMsgLvl::Err, msg );
		throw("(Err:94)");
	}
	#endif //ZSCATCH
TszPo szmem = _szUPool * sizeof(TBitUnit);
    memset( _pool, 0, szmem );  //ZeroMemory( _pool, szmem );
ezus
() автор топика
Ответ на: комментарий от ezus

_pool= NULL;

allsz забыл уменьшить раз уж выделить память не получилось.

Или увеличивать только после успешного выделения памяти.

ox55ff ★★★★★
()
Ответ на: комментарий от ox55ff

Выражения хранятся в виде ссылок на термы, а термы - битовые маски.

Подскажи, пожалуйста, как мониторить свободную память в linux

ezus
() автор топика
Ответ на: комментарий от ox55ff

Если памяти не хватает, то вычисление прерывается, и все становится невыжным.

ezus
() автор топика
Ответ на: комментарий от ox55ff

Мониторь свободную память системы без учёта файловых кэшей. Как только подойдёт к 100% (95%, 90%), то завершай работу.

Ну вот посмотрел он, а там 100%, и он решил завершаться, а потом сразу стало свободно 95%, и памяти хватило бы, но он уже завершился. Это не решение проблемы.

seiken ★★★★★
()
Ответ на: комментарий от ezus

Приведенное «решение» решает проблему крайне плохо. Нет никакой гарантии того, что между проверкой файла и выделением памяти ситуация не изменится, не говоря уже о том, что эта информация никак не сообщает о том, какова нагрузка на систему и какая память может быть вытеснена, а какая – нет.

Так или иначе, выполнять cat не нужно, достаточно использовать обычные средства текстового ввода из файла, например fopen или std::ifstream, передавая им путь /proc/meminfo.

Siborgium ★★★★★
()
Ответ на: комментарий от seiken

Это еще нормальная ситуация в результате которой приложение аккуратно завершится.

А случиться может наоборот: он посмотрел, и там 95%, но к моменту выделения окажется 100% – но этого он уже не узнает, и приложение посыпется.

Siborgium ★★★★★
()

Удивлён что никто не указал на

man set_new_handler

Ну, а дальше сами уж думайте что делать когда память кончается - толи сразу завершаться, толи поспать и повторить N раз и только потом завершаться. И ещё - в 32 битах можно поиметь bad_alloc задолго до того как физическая память кончится, так что все эти попытки подсмотреть в /proc/meminfo - от лукавого.

bugfixer ★★★★★
()
Ответ на: комментарий от Siborgium

Ну вот, т.е. с таким подходом всё равно может быть сегфолт, и зачем тогда городить огород, если он всё равно не сработает? Логично для таких случаев опционально для конкретных процессов отключать этот оптимистический режим менеджера памяти.

seiken ★★★★★
()
Ответ на: комментарий от ezus

Нет. Cat чтобы изучить содержимое глазами. В программе читай как текстовый файл.

ox55ff ★★★★★
()
Ответ на: комментарий от Begemoth

Как я понял ТС, у него включен overcommit и он ничего не видит, а только segfault когда ядро не может страницу ему закоммитить, но это уже сильно позже того как new отработал

Ни разу такого не видел - на глубокий swap/OOM kill можно нарваться, но так чтобы именно segmentation fault - никогда.

bugfixer ★★★★★
()
Ответ на: комментарий от seiken

Если ты балансируешь на грани, то это не нормальная ситуация. Должен быть запас по памяти. Так что если докатились под потолок по памяти, то нужно завершаться и звать админа или разработчики разбираться.

ox55ff ★★★★★
()
Ответ на: комментарий от ox55ff

В первую очередь нужен механизм надёжного и безопасного завершения процесса, а не по сегфолту. Хотя если система рассчитана на «have you tried turning it off and on again?», то конечно пофиг.

seiken ★★★★★
()
Ответ на: комментарий от seiken

В первую очередь нужен механизм надёжного и безопасного завершения процесса

Очень нетривиальная задача, должен заметить. Придётся на старте mlock’чить «резерв», и переключаться на этот «резервный» аллокатор на время shutdown (затрудняюсь представить как можно сделать что-то осмысленное совсем не выделяя ничего из heap, а память уже закончилась).

bugfixer ★★★★★
()
Ответ на: комментарий от ezus

Не комплируется:

gcc lor.cpp 
lor.cpp:1:1: error: ‘ZSTRY’ does not name a type
    1 | ZSTRY  //try
      | ^~~~~
lor.cpp:15:1: error: ‘TszPo’ does not name a type
   15 | TszPo szmem = _szUPool * sizeof(TBitUnit);
      | ^~~~~
lor.cpp:16:11: error: expected constructor, destructor, or type conversion before ‘(’ token
   16 |     memset( _pool, 0, szmem );  //ZeroMemory( _pool, szmem );
      |           ^
LamerOk ★★★★★
()
Ответ на: комментарий от EXL

Не спасёт от оверкоммита. Упадёт уже при попытке доступа к памяти.

ox55ff ★★★★★
()
Ответ на: комментарий от ezus

У тебя дисклексия?

Приведи минимальный пример воспроизводимой проблемы.

LamerOk ★★★★★
()

Я был влюблен в UNIX с середины 80-х, а затем моя любовь перешла на Linux, но здесь явное «горе от ума».

Я всегда относился к Windows с подозрением и неприязнью, но таких проблем с выделением памяти, такой очевидной и частой ситуацией, я не встречал ни разу.

ezus
() автор топика

Как по мне в современном linux проблема не решается - слишком много может быть и всё учесть не реально. Решение простое - пусть пользователь сам скажет, через параметр сколько он может памяти выделить твоей проге.

vtVitus ★★★★★
()
Ответ на: комментарий от ezus

но таких проблем с выделением памяти, такой очевидной и частой ситуацией, я не встречал ни разу.

Как я помню, возврат null при выделении памяти в win это не значит, что памяти нет. Это значит, что система в данным момент не может тебе её предоставить. Соответственно подождав небольшой timeout можно её попросить ещё раз и, о чудо, она может появиться. Та ещё магия. А что сейчас там с памятью, даже думать не хочется.

vtVitus ★★★★★
()
Ответ на: комментарий от vtVitus

Все это верно, но меня в данной ситуации интересует только получил я память или нет.

ezus
() автор топика
Ответ на: комментарий от ezus

Ты первый раз в Интернет что ли? Если исходников много, выделяют маленький кусок, который содержит и представлет проблему. Если его надо доделать-переделать, чтобы он собирался - это твоя работа.

seiken ★★★★★
()
Ответ на: комментарий от seiken

Ты никогда не сталкивался с нехваткой памяти?

Зачем тебе код? Запроси 22.000.000.000 и посмотри на результат.

Вопрос, мне кажется, абсолютно прозрачным: «Я получил память для использования или нет?»

ezus
() автор топика
Последнее исправление: ezus (всего исправлений: 1)
Ответ на: комментарий от ezus

mlock посмотри.

mlock() locks pages in the address range starting at addr and continuing for len bytes. All pages that contain a part of the specified address range are guaranteed to be resident in RAM when the call returns successfully; the pages are guaranteed to stay in RAM until later unlocked.

ox55ff ★★★★★
()
Ответ на: комментарий от upcFrost

Смотря для чего. В 99% случаев хватит либо го/жабы/питона, либо сишки без крестов

К сожалению, никакие жабы не проходят по производительности.

А чем сишки без крестов отличаются от крестов?

ezus
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.