LINUX.ORG.RU

malloc() не хочет отдавать NULL

 , , , ,


0

2

Не могу добиться от malloc возврата NULL!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>

int main()
{
	clock_t tmstmp;

	tmstmp = clock();
	printf("clock = %ld\n", tmstmp);

	size_t gb24 = 24LU*1024*1024*1024;
	volatile unsigned char* pre_mem = malloc(gb24);
	for (size_t i = 0; i < gb24; i += sizeof(clock_t)) {
		*(pre_mem + i) = clock();
	}
	//uint_t offset = 0;
	//explicit_bzero(pre_mem, gb24);
	printf("starting the loop\n");
	tmstmp = clock();
	printf("clock = %ld\n", tmstmp);
	fflush(stdin);

	size_t counter = 0;
	for(;counter < 12345678;++counter) {
		//*(pre_mem + offset) = counter;
		//offset += (sizeof(counter));

		size_t mem_size = 64*1024;
		volatile unsigned char* mem = malloc(mem_size);
		for (size_t i = 0; i < mem_size; i+=sizeof(clock_t)) {
			*(mem+i) = clock();
		}
		if (NULL == mem) {
			printf("iter %lu: NULL\n", counter);
			break;
		} else {
			for (size_t i = 0; i < mem_size; i+=sizeof(clock_t)) {
				*(mem+i) = clock();
			}
			*(mem + counter%(4096)) = counter;
		}
	}

	return counter % 123456789;
}

У меня на машине 16ГБ озу и 32 свопа.

/tmp ❯❯❯ journalctl -k --since "-5 minutes" | grep -i -E 'out of memory|oom-killer|memory cgroup|Killed process'
Nov 16 18:09:49 g16 kernel: nvim invoked oom-killer: gfp_mask=0x140cca(GFP_HIGHUSER_MOVABLE|__GFP_COMP), order=0, oom_score_adj=0
Nov 16 18:09:49 g16 kernel: Out of memory: Killed process 428379 (a.out) total-vm:29233540kB, anon-rss:9961472kB, file-rss:724kB, shmem-rss:0kB, UID:1000 pgtables:57260kB oom_score_adj:0

если не инициализировать всю память, а только «местами», то краш случается, когда виртуальной памяти отдано уже 80-110 гигов.

Помогите получить от malloc NULL!!

А то что это получается, не надо чекать что там вернул malloc?

Есть интереснее вариант: выделяешь кучу памяти и инитишь её. дальше форкаешься и снова инитишь память.

«ulimit -Hv» или setrlimit в помощь.

vel ★★★★★
()

А то что это получается, не надо чекать что там вернул malloc?

Проверять надо, но уже лет 20 как, если не больше, он фактически не проверяет количество памяти. Есть какой-то параметр для sys чтобы управлять агрессивностью выделения.

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

Короткие тоже либо в mmap либо в sbrk (вроде его депрекейтить собирались в пользу того же mmap, не знаю чем закончилось). Просто не 1 к 1 а много malloc-ов на 1 сисколл.

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

Поэтому в коде я выделяю маленькими кусочками, по 64кБ. Только толк-то нет. mmap() не вызывается, я смотрел через strace. Но память всё равно не настоящая.

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

Поэтому в коде я выделяю маленькими кусочками, по 64кБ.

Само по себе это не плохо и не хорошо (в предположении что вы там не велосипедите, а действительно 64kb chunks нужны), но аргументация крайне странная - абсолютно ничего криминального в mmap() нет.

mmap() не вызывается, я смотрел через strace. Но память всё равно не настоящая.

Я думаю до первого page fault с точки зрения overcommit management монопенисуально откуда память пришла. На коротких аллокациях я бы ожидал sbrk() увидеть.

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

меня на машине 16ГБ озу и 32 свопа

У меня получалось, если попросить выделить за раз больше памяти, чем есть оперативной памяти и подкачки вместе взятых. У меня 16+16, поэтому прошу в районе 32 гигабайт:

$ echo -e '#include<stdio.h>\n#include<stdlib.h>\nmain() { printf("%p\\n", malloc(31e9)); }'  | tcc -run -
0x7f8199018010
$ echo -e '#include<stdio.h>\n#include<stdlib.h>\nmain() { printf("%p\\n", malloc(33e9)); }'  | tcc -run -
(nil)
anonymous
()
Ответ на: комментарий от bugfixer

Я же не спорю. Я не против mmap, а очень даже за, учитывая что можно крутить MMAP_THRESHOLD. Меня удивляет, что тогда, когда mmap не вызывается, я всё равно не получаю реальной памяти! Я хочу NULL, когда знаю, что mmap не будет вызван и реальной памяти нет — потому что хочу продолжить работу программы или корректно завершиться. Оказывается, что, с настройками по умолчанию, случается не NULL, а sigkill на доступе))

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

Дело не в самом сисколле mmap. mmap это просто интерфейс к ядерному аллокатору. А так что mmap что brk делают одно и то же и зависят от одних и тех же настроек.

Касательно brk/sbrk. При запуске тоей проги ей выделяется начальный кусок памяти под её обычные переменные. Выделяется, разумеется, на тех же основаниях что и mmap, но исторически конкретно этот кусок памяти чуть-чуть особенный - его можно ресайзить сисколлами brk/sbrk. Так получилось исключительно потому что в старых юниксах mmap вообще не было. Но выделение памяти работает и там и там через одинаковые ядерные механизмы.

firkax ★★★★★
()

Аллоцируй больше, чем у тебя доступно адресного пространства.

#include <stdlib.h>
#include <stdio.h>

int main( int argc, char **argv )
{
        void *p = malloc( -1 );
        if( !p )
                puts( "malloc NULL" );


        return 0;
}
a1ba ★★★
()
Ответ на: комментарий от Psilocybe
Nov 17 10:22:47 g16 kernel: thermald invoked oom-killer: gfp_mask=0x140cca(GFP_HIGHUSER_MOVABLE|__GFP_COMP), order=0, oom_score_adj=0
Nov 17 10:22:47 g16 kernel: Out of memory: Killed process 514191 (a.out) total-vm:34449340kB, anon-rss:9645568kB, file-rss:1212kB, shmem-rss:0kB, UID:1000 pgtables:67460kB oom_score_adj:0
BruteForce ★★★
() автор топика

malloc() не хочет отдавать NULL

Хотя это не по теме, но поверьте весьма полезно и многие вопросы решает.
У меня своя подсистема управления памяти.
Не универсальная, а для своего API.
Весьма удобно.

Профит в чём?

Устраняет проблемы утечки памяти, весьма быстрая, …

anonymous
()
Ответ на: комментарий от BruteForce

Но память же ты должен откуда-то получить?

Конечно!

Ээээээээээээээ, в «этом болотистом низменном крае» много интересного - ВЕСЬМА ИНТЕРЕСНОГО.
Это на первый взгляд так кажется, что подсистема управления памятью уныла.
Нырните - СОВЕТУЮ.
Там иной интересный мир.

anonymous
()

Чувак, ты в местах не столь отдаленных пропустил эпичный тред, где царь утверждал, что результат malloc проверяют только анскиллед лалки, по причине уже озвученой)

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

Если по 64Кб, так может куску mlock сделать (RLIMIT_MEMLOCK вроде как раз столько по умолчанию). Если mlock не прошёл, то и привет - памяти нет, если прошёл - то munlock() и погнали дальше.

Там правда ограничения только для root процессов, вроде.

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

Да, это понятно. Пулы, линейные аллокаторы, бакетайзеры и тадалее и тадалее. Но память же ты должен откуда-то получить?

В любой ОС подсистема управления памятью непроста.
А если ещё к этому добавить вопросы свящанные с выгружаемой памятью, … (этих «закарлючек» немало).
Вот недавно патч по пулам памяти Торвальдс принял.
Что могу сказать по этому поводу?
Интересный патч, но бывают и иные алгоритмы повышения эффективности.
У меня конечно API не панацея, но радует.
В этих задачах весьма много работы.
И то что сделал многие вопросы решает, но можно много лучше.
Пока для меня эта задача вовсе не приоритетна.

Если честно говоря то свою подсистему управления памяти разработал с акцентированием быстрого доступа к данным в памяти и файлах.
Это не простой вопрос (поверьте на слово).

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

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

Гм., преувеличил.
Уже многое радует, но работы ещё МНОГО.
Этот «болотистый край» от себя так просто не отпустит.

anonymous
()
Ответ на: комментарий от LongLiveUbuntu

Только на правду не похоже, OOM не приходит, а NULL возвращается:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(void) {
    void* tmp = malloc(PTRDIFF_MAX);
    printf("tmp := %p\n", tmp);
    return 0;
}
$ ./malloc
tmp := (nil)
Ja-Ja-Hey-Ho ★★★★★
()

Да, из-за этого рака с overcommit и говнокодерами, которые в расчёте за overcommit алооцируют мегатонны памяти получилась такая неприятная история, что на разумных запросах памяти ты не получишь отказу (сразу). Из-за этого даже при разумных настройках ulimit многие привычные программы просто не могут работать.

Наверное, есть платформы, где не так, какие-нибудь embedded, телефоны или приставки.

legolegs ★★★★★
()