Как-то так. Вычисляет размер максимально большого свободного блока и суммарный размер первых нескольких больших блоков, что даёт аппроксимацию свободного объёма памяти в целом и сведения о фрагментации. Работает с любой IDE, любым компилятором, любой ОС, любой библиотекой... где есть malloc. Выполняется относительно медленно. Ограничение в MAX_SIZE нужно для того, чтобы в среде linux не глючил valgrind, не срабатывали лимиты (ulimit) и linux не выделял бы бесконечное количество памяти. В системе без виртуальной памяти ограничение не нужно.
#include <stdlib.h>
#include <stdint.h>
#include <limits.h>
#include <assert.h>
#include <stdio.h>
struct s_memfree {
size_t maxsize; // макс. размер свободного блока
size_t minfree; // объём свобнодной памяти равен или больше minfree
unsigned nblocks; // число блоков в minfree
};
#ifndef TEST_MEMFREE
#define LIMIT 16 /* usually ok for embedded platform */
#define MALLOC malloc
#define FREE free
#else /* TEST_MEMFREE */
#define LIMIT 16
void *MALLOC(size_t n);
void FREE(void *p);
#endif
/* because of OS limits, etc... */
#if SIZE_MAX <= (64*1024*1024/LIMIT)
#define MAX_SIZE SIZE_MAX
#else
#define MAX_SIZE (64*1024*1024/LIMIT)
#endif
/* allocate block with maximum possible size and return pointer
* to it (block contains it's size), return NULL if block can't be allocated */
static size_t *maxblock(size_t max)
{
uint_fast8_t count=0;
size_t bs, min=sizeof(size_t);
size_t *p=NULL;
while (max > min) {
if (p!=NULL) FREE(p);
bs=((unsigned long)max+min)/2+1;
p=MALLOC(bs);
if (p==NULL) max=bs-1;
else *p=bs, min=bs;
count++;
assert(count < 48); /* log2(2^32) */
}
if (p==NULL) p=MALLOC(min);
if (p!=NULL) *p=min;
return p;
}
/* compute summary size of free blocks with `max' size limit,
* number of iterations limited by `limit' value */
static size_t minfree(size_t max, unsigned limit, unsigned *nblk)
{
size_t s, *p;
p=maxblock(max);
if (p==NULL) return 0;
if (nblk!=NULL) (*nblk)++;
if (limit>0) s=minfree(*p, limit-1, nblk);
else s=0;
s+=*p;
FREE(p);
return s;
}
// возвращает размер свободного блока максимального размера
size_t maxfree(void)
{
size_t s, *p=maxblock(MAX_SIZE);
if (p==NULL) return 0;
s=*p;
FREE(p);
return s;
}
// возвращает минимальный объём свободной памяти и заполняет структуру (см. выше)
size_t memfree(struct s_memfree *r)
{
struct s_memfree my;
size_t *p;
if (r==NULL) r=&my;
r->maxsize=0, r->minfree=0, r->nblocks=0;
p=maxblock(MAX_SIZE);
if (p==NULL)
return 0;
r->maxsize=*p;
r->nblocks++;
r->minfree=r->maxsize+minfree(r->maxsize, LIMIT, &r->nblocks);
FREE(p);
return r->minfree;
}
[ZX]