Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Получение свободного объема кучи
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
YChebisheva
Есть ли какие-нить макросы, чтобы в ходе работы можно было знать, к примеру, адрес начала, конца и сколько осталось свободного места в куче?
etoja
Цитата(YChebisheva @ Mar 24 2009, 12:14) *
Есть ли какие-нить макросы, чтобы в ходе работы можно было знать, к примеру, адрес начала, конца и сколько осталось свободного места в куче?


Адрес начала кучи вам даст функция malloc, например:

char *p;
p = malloc(1); // просим выделить 1 байт из кучи

Размер кучи вы задаёте в свойствах проекта: Linker->Heap Size.
FormatCft
Цитата(etoja @ Mar 24 2009, 14:33) *
Адрес начала кучи вам даст функция malloc, например:

char *p;
p = malloc(1); // просим выделить 1 байт из кучи

Размер кучи вы задаёте в свойствах проекта: Linker->Heap Size.


Вы уверены, что вновь выделяемый кусок будет именно в конце?


(из любопытства)
_Pasha
Цитата(YChebisheva @ Mar 24 2009, 12:14) *
и сколько осталось свободного места в куче?

Я оборачивал malloc/calloc/realloc/free в свои функции, в которых отслеживал задаваемый в параметрах размер. Типа того:

Код
static size_t mem_avail = 1024;// здесь размер кучи

void *malloc_prim(size_t size)
{
void *p;
p = malloc(size);
if(p!=NULL) mem_avail -=size;
return p;
}
#define malloc(sz) malloc_prim(sz)


УПС: порядок имеет значения #define после всей работы с настоящими malloc итд.
FormatCft
Цитата(YChebisheva @ Mar 24 2009, 14:14) *
Есть ли какие-нить макросы, чтобы в ходе работы можно было знать, к примеру, адрес начала, конца и сколько осталось свободного места в куче?

Лучше ипользовать какой-нибудь открытый аллокатор.

Можно взять "монументальный" TLSF. В составе есть get_used_size.


Ну а если со стандартным, то можно написать так:

1) Разметка всего хипа опред числом.

2) При маллоке портим значение выделяемой области. Меняем на др чилсло.

3) При осовбождении востанавливаем число.

4) При вычислении считаем количество "испорченных".

Этот метод позовляет вычислить с достаточной степенью точности +\- 10 километров (шутка).
klen
я использую FreeRTOS, там есть три реализации maloc/free, я взял одну из них и добавил в нее все что мне нада, в том числе и функцию возвращающуую остаток кучи, могу исходник кинуть если хотите
FormatCft
Цитата(klen @ Mar 24 2009, 14:56) *
я использую FreeRTOS, там есть три реализации maloc/free, я взял одну из них и добавил в нее все что мне нада, в том числе и функцию возвращающуую остаток кучи, могу исходник кинуть если хотите

Из всех 3х реализаций ровно ноль нормальных (Исключительно ИМХО).

По-моему при создании фриртоса ставилась основная цель: сделать добротный движок, но не было цели сделать номальный аллокатор.


Потому как хороших открытых и закрытых (в средах разработки) аллокаторов довольно много. Выбирайте на любой вкус.
klen
Цитата(FormatCft @ Mar 24 2009, 13:05) *
Из всех 3х реализаций ровно ноль нормальных (Исключительно ИМХО).

По-моему при создании фриртоса ставилась основная цель: сделать добротный движок, но не было цели сделать номальный аллокатор.


Потому как хороших открытых и закрытых (в средах разработки) аллокаторов довольно много. Выбирайте на любой вкус.


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

поповоду фриртоса полностью согласен - не барское дело аллокатор писать smile.gif вед он и нужен в подразумераймых системах обычно только от скуки программиста, или от его кривости рук. За все время не помню задачу чтоб без malloc/free можно было выполнить задачу, обычно наоборот требуют чтоб такого "разгильдяйства" как maloc/free небыло maniac.gif
YChebisheva
Парни, у меня не стоит задача, оптимизировать работу с памятью.
Если я смотрю map-файл:

.heap 0x40002458 0x400
0x40002458 __heap_start__ = .
*(.heap)
0x40002858 . = (((__heap_start__ + __HEAPSIZE__) MAX_K .) ALIGN 0x4)
*fill* 0x40002458 0x400 00
0x40002858 __heap_end__ = (__heap_start__ + SIZEOF (.heap))
0x00000001 . = ASSERT (((__heap_end__ >= __SRAM_segment_start__) && (__heap_end__ <= (__SRAM_segment_start__ + 0x4000))), error: .heap is too large to fit in SRAM memory segment)
0x40002858 __stack_load_start__ = (__heap_end__ ALIGN 0x4)

Получается, что у меня куча начинается с 0x40002458. Объем 1 Кб. Его размер я могу поменять. Память выделяет с конца кучи к началу.
Но сразу после инициализации, я делаю так:
Код
system_init();
spi0_mem_init();
ctl_global_interrupts_enable();    
UART0Initialize(38400, InterruptCom0);
char *s = (char*) malloc(1);
printf("     %p      ", s);
free(s);

Адрес s мне показывается - 284с. А конец кучи - 2858. Вроде как 13 байт. Но почему не 16? Ведь если следом запросить, к примеру 5 байт из кучи, адрес будет - 283с.
_Pasha
Цитата(YChebisheva @ Mar 24 2009, 15:07) *
Если я смотрю map-файл:
0x40002858 __heap_end__ = (__heap_start__ + SIZEOF (.heap))


Если линкер поставляет Вам (компилеру)  __heap_end__ , то зачем эти пассы:

Код
char *s = (char*) malloc(1);



если можно просто s=__heap_end__;
YChebisheva
Цитата(_Pasha @ Mar 24 2009, 15:24) *
Если линкер поставляет Вам (компилеру)  __heap_end__ , то зачем эти пассы:
Код
char *s = (char*) malloc(1);

если можно просто s=__heap_end__;

В том то и беда, что на все эти попытки, имеем одно:
Цитата
'__heap_end__' undeclared (first use in this function
_Pasha
Цитата(YChebisheva @ Mar 24 2009, 15:39) *
В том то и беда

Даже как extern void* __heap_end__; ?
YChebisheva
_Pasha, левые адреса возвращает:

printf("%p", __heap_end__);
6f2cbea3
sad.gif
FormatCft
Цитата(YChebisheva @ Mar 24 2009, 18:14) *
_Pasha, левые адреса возвращает:

printf("%p", __heap_end__);
6f2cbea3
sad.gif

Описал так:

extern void * __heap_start__;
extern void * __heap_end__;



volatile void * heap_start = &__heap_start__;
volatile void * heap_end = &__heap_end__;
Всё отлично.
_Pasha
Это я глупость сморозил, должно быть так:

Код
extern char __heap_end__;

int main(void)

{

//фигли-мигли

void * s = (void *) &(__heap_end__);

}
YChebisheva
Спасибо. Всё работает
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.