LINUX.ORG.RU

Свои аллокаторы и виртуальные методы


0

1

Всем привет, решил сам организовывать память в своих приложениях, и написал свои простые аллокаторы памяти, все работает прекрасно, но одна проблема: если в классе есть виртуальные методы, то они почему-то не хотят вызываться, и постоянно вылетает ошибка segmentation fault. Почему так? понятно что под виртуальные методы отдельно выделяется память, но я пробовал уже и по 1МБ под класс выделять, один фиг не хочет работать :( Вот код пуллового аллокатора:

/*!< Pool Allocator >!*/
//
void CreatePoolBuffer(PoolBuffer *buf, uint32_t size, uint32_t chunkSize) {
	//
	buf->totalSize = size;
	buf->chunkSize = chunkSize;
	buf->mem = (uint8_t*)mmap(0, size, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	//
	const uint32_t chunkCount = (size / chunkSize) - 1;
	
	for (uint32_t i = 0; i < chunkCount; ++i) {
		uint8_t* currChunk = buf->mem + (chunkSize*i);
		*((uint8_t**)currChunk) = currChunk + chunkSize;
	}
	
	*((uint8_t**)&buf->mem[chunkCount * chunkSize]) = 0;
	buf->head = buf->mem;
	//
}

//
inline void* PoolAlloc(PoolBuffer* buf) {
	//
	uint8_t* currPtr = buf->head;
	buf->head = (*((uint8_t**)(buf->head)));
	return currPtr;
}

★★★

Ответ на: комментарий от Int64

Так в этом и проблема. Ты конструкторы-то вообще не вызываешь. Даже дефолтные. Кто у тебя будет заполнять таблицы виртуальных функций? Сделай нормальный аллокатор, подобно std::allocator. Ну или operator new перегрузи. Это же кошмар, что ты показал.

anonymous
()
Ответ на: комментарий от Int64
Obj = (ObjType*)PoolAlloc(PoolBuffer);
Obj->Init();
Obj = new(PoolAlloc(PoolBuffer))ObjType();
gv
()

Шо-то мне это напоминает «Цэпепе фор рил программерс» какого-то джаффа.

HNO-Arzt_
()
Ответ на: комментарий от Int64

Obj->Init(); // Вместо конструктора

Вот тут-то и ошибка. Конструктор это не только ваш код, но еще и закулисные действия, в том числе и инициализация vtbl.

Пути решения:

placement new - самый легкий в вашем случае путь, но он потребует всегда получать сначала указатель, а так же заставит вызывать руками деструкторы.

Перегрузка стандартных operator new(глобально или только для вашей иерархии типов) - способ тоже простой, но ненаглядный при чтении кода.

Своя версия перегрузки operator new в которую вы передаете свой объект для выделения памяти(инстанс PoolBuffer'а или как там он у вас называется). Так же потребует некой дополнительной функции для уничтожения объектов, которая будет дергать деструктор, а затем возвращать память.

Реализация полноценного аллокатора(под требования Стандарта), позволит использовать свою стратегию управления памятью со стандартными(и сторонними) контейнерами. Можно сочетать с предыдущим пунктом.

forCe
()

решил сам организовывать память в своих приложениях

Да ты у мамы хакир! А тимлид знает?

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от forCe

спасибо большое, вроде заработало )

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