LINUX.ORG.RU

man расхлябанность.

У меня периодически течет.

Eddy_Em ☆☆☆☆☆
()

Когда программа освобождает память это еще не значит, что эту память может использовать другая программа. Все не просто. Да и память обычно утекает не потому что кто-то клинический идиот, а потому, что кто-то не «освобождает» переменные.

soomrack ★★★★★
()

Прибилизительно по той же причине, по которой возникают все остальные ошибки. Утечки кода нередко возникают на стыке разных компонент, особенно написанных третими лицами не знающих друг о друге.

А вообще даже в языках с GC утечки памяти не так редки.

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

Вот.

В данном случае, выделяется только память вида двумерный массив double, но это легко обобщается.


#ifndef __MEMMAN_H__
#define __MEMMAN_H__

#include "types.h"

class array2
{
	int count;
	void free();
	int temp;
	public:
		uint w, h;
		double** m;
		array2();
		~array2();
		int allocate(uint w0, uint h0);
		void link();
		void unlink();	
		void temp_clear();
		void set_temp();
		void set_pers();
};


void mem_free();

array2* mem_alloc(uint w, uint h);

void mem_clean();
void temp_clear();

int if_clean();

#endif





#include <stdio.h>
#include "memman.h"

array2::array2()
{
	temp = 0;
	count = 0;
	m = NULL;
	w = 0;
	h = 0;
}

array2::~array2()
{
	if (m != NULL)
		array2::free();
	m = NULL;
	w = 0;
	h = 0;
}

void array2::set_temp()
{
	temp = 1;
}


void array2::set_pers()
{
	temp = 0;
}

void array2::temp_clear()
{
	if (temp)
	{
		count = 0;
		unlink();
	}
}



void array2::free()
{
	int i;
	if (m == NULL)
		return;
	for (i = 0; i < h; i++)
	{
		delete m[i];	// m[i] != NULL
	}
	delete m;
	m = NULL;
	w = 0; 
	h = 0;
}

int array2::allocate(uint w0, uint h0)
{
	int i;
	if (m != NULL)
		return -2;	//already allocated
	if (w0 * h0 == 0)
		return -1;	//zero size

	w = w0;
	h = h0;
	m = new pdouble[h];
	if (m == NULL)
	{
		w = 0;
		h = 0;
		return -1;	//no mem
	}
	
	for (i = 0; i < h; i++)
	{
		m[i] = new double[w];
		if (m[i] == NULL)
			goto nomem;
		for (int j = 0; j < w; j++)
			m[i][j] = 0;
	}
	
	return 0;
nomem:
	i--;
	while (i >= 0)
	{
		delete m[i];
		--i;
	}
	delete m;
	m = NULL;
	w = 0;
	h = 0;
	return -1;	//no mem
}

void array2::link()
{
	count++;
}

void array2::unlink()
{
	count--;
	if (count <= 0)
		array2::free();
}


struct memlist
{
	memlist *prev, *next;
	array2 val;
	memlist();
};

memlist::memlist()
{
	prev = NULL;
	next = NULL;
}

memlist *list = NULL;


void temp_clear()
{
	memlist *pnt = list;

	while (pnt != NULL)
	{
		pnt->val.temp_clear();
		pnt = pnt->next;
	}
}


void mem_free()
{
	memlist *next;
	while(list != NULL)
	{
		next = list->next;
		delete list;
		list = next;
	}
}

array2* mem_alloc(uint w, uint h)
{
	memlist *newel = new memlist();
		
	if (newel == NULL)
		return NULL;
	if (newel->val.allocate(w, h) < 0)
	{
		delete newel;
		return NULL;;
	}
	newel->next = list;
	list = newel;
	newel->val.link();
	return &(newel->val);
}

void mem_clean()
{
	memlist *pnt = list;
	while (pnt != NULL)
	{
		if (pnt->val.m == NULL)		//element is empty
		{
			memlist *prev = NULL, *next = NULL;
			prev = pnt->prev;
			next = pnt->next;
			if (prev != NULL && next != NULL)	// middle of the list
			{
				prev->next = next;
				next->prev = prev;
				delete pnt;
				pnt = next;
			}
			else if (prev == NULL && next != NULL)	// begin of the list
			{
				next->prev = NULL;
				delete pnt;
				pnt = next;

				list = next;
			}
			else if (prev != NULL && next == NULL)  // end of the list
			{
				prev->next = NULL;
				delete pnt;
				pnt = prev;
			}
			else	// the only element in the list
			{
				delete pnt;
				pnt = NULL;

				list = NULL;
			}
		}
		else
			pnt = pnt->next;
	}	
}


int if_clean()
{
	if (list == NULL)
		return 1;
	return 0;
}

cvs-255 ★★★★★
() автор топика

Если уж использовать менеджер то не проще ли использовать язык где менеджер уже есть?

DNA_Seq ★★☆☆☆
()

Ну некоторые вообще не знают, что память нужно освобождать :)

Ttt ☆☆☆☆☆
()
Ответ на: комментарий от cvs-255

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

DNA_Seq ★★☆☆☆
()
Ответ на: комментарий от cvs-255

Данный код писался для работы с умножениями матриц произвольного размера.

В основном, он заточен для избегания утечек и повторного освобождения.

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от DNA_Seq

Оно же тормозит!

Тут же такая дилемма получается: или просто, но мееедленно, или быстро, но сложно!

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

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

Либо написать менеджер памяти для конкретной задачи.

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от Makefile

Зачем кресты? По условию нужно C или C++.

Для моей задачи нужно много умножать матрицы. Это удобнее в C++.

cvs-255 ★★★★★
() автор топика

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

note173 ★★★★★
()
Ответ на: комментарий от cvs-255

Это удобнее в C++.

А нифига подобного. С матрицами плевать, где работать. Там никакого наследования и т.п., за что удобно пользовать плюсы, нет. А на С кода меньше писать, чем на плюсах. И меньше шансов ошибиться.

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

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

А вот Java дает куда больший оверхед.

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

Данный код писался для работы с умножениями матриц произвольного размера.

В основном, он заточен для избегания утечек и повторного освобождения.

Не факт. Рассмотри такую ситуацию:

1. выделение непрерывного куска памяти под матрицу 1000 х 1000

2. освободение этой памяти

3. выделение непрерывного куска памяти под матрицу 1001 х 1001

Вопрос сколько памяти будет числиться за программой после шага 3 ?

~1.000.000 или ~2.000.000 ?

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

А нафиг вообще в юниксах треды? А под виндой перл юзают истинные мазохисты.

Затем, зачем и везде. Чтобы была общая память для разных потоков вычислений.

soomrack ★★★★★
()

В libixp был баг. Для уменьшения количества вызовов malloc/free сделали пул свободных блоков. Код который раньше делал malloc/free теперь делает некий pool_malloc/pool_free который забирает/отдает блок в/из свой список. В одном месте остался вызов malloc. Результат, тот список неограниченно возрастатет, и это не утечка, хотя последсвия такие же.

amaora ★★
()

Чем поможет твой следящий менеджер? Сам найдет место, где теряется указатель на блок памяти? Без тестов таких мест автоматически не найти, а с тестами можно и valgrind'ом найти.
Мусор надо детектировать уровне языка => java, lisp, etc.

Makefile
()

Как люди умудряются строить дома, которые разваливаются через 100 лет?
Ведь кулечки в песочнице можно сделать за несколько секунд?
П.С.
Твой двухмерный массив не годится для приложений где требуется высокая производительность. У тебя же он фрагментирован будет как не знаю что.

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

Когда программа освобождает память это еще не значит, что эту память может использовать другая программа. Все не просто.

man brk|sbrk|mmap

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

У меня, после освобождения памяти, память освобождается. Вся память выделяется из кучи.

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

когда я делаю

array2* ar2 = ar1;
ar2->link();


Я имею блок памяти, на который ссылается 2 указателя.

Когда ar2 или ar1 больше не нужен, я делаю unlink();

Для длинных выражений, вроде приведенных выше, где я не имею явного указателя на объект и unlink() не вызвать, я использую массивы с установленным флагом временности. Их освобождает сборщик мусора.
cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от cvs-255

У меня, после освобождения памяти, память освобождается. Вся память выделяется из кучи.

Скажи об этом операционной системе.

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

С матрицами плевать, где работать.

А как же перегрузка операторов? Наверно и диапазоны индексов можно сделать, и ещё, что нибудь, будет почти matlab/octave, нет?

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

Сам найдет место, где теряется указатель на блок памяти?

Он помогает просто писать link, там где начинается работа с указателем и unlink, там где заканчивается работа с этим указателем.

А за тем, чтобы все выделялось и освобождалось, следит менеджер.

Он же подчищает оставшийся мусор, который помечен как temp.

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

Конечно. По сути-то в результате получается одно и то же.

Мне нравится удобочитаемый код.

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

Забудешь сделать unlink(), так же, как забывал сделать free(). В чем разница? А этот твой флаг временности — билет в страну Сегфолию.

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

Это уже проблема ОС, как она там выделяет. Я слежу за тем, чтобы моя программа не теряла указатели.

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

Иногда хочется производительности

ява не тормозит. Это всё сказки упоротых сишников.

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

Я к сишечке привык. Меня эта перегрузка операторов только с толку сбивает.

будет почти matlab/octave

Эти у меня прочно ассоциируются с эдакими ардуинами математики: годятся, только если тебе надо что-то по-быстрому посчитать один раз. И забыть. Ну или сделать модель, потыкать ее, а потом переписать на нормальном ЯП.

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

так же, как забывал сделать free(). В чем разница?

Разница колоссальна. Для корректного написания free, когда на одну и ту же память ссылается много указателей, требуется много усилий, чтобы с одной стороны, очистить то, что надо очистить, а с другой не очищать то, что уже очищено.

Тут же за этим следит система.

А этот твой флаг временности — билет в страну Сегфолию.

Ничего подобного.

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

cvs-255 ★★★★★
() автор топика

Ведь удобный менеджер памяти, следящий за выделением и освобождением памяти пишется за пару часов?

...для твое конкретной задачи. А нужен менеджер памяти общего назначения.

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

А нужен менеджер памяти общего назначения.

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

cvs-255 ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

«всякие тормозящие» тормозят примерно на 30%, а то и меньше, на числодробилках, не говоря уже о большее сложных вещах.

qnikst ★★★★★
()
Ответ на: комментарий от cvs-255

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

Сколько человек писали твою программу?

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