C语言自动管理动态分配内存的一种方法

C语言自动管理动态分配内存的一种方法

正常情况下用malloc分配内存,用free释放内存,用realloc重新分配,分配的内存必须要释放,我们的思路是自定义一个函数my_alloc,用户调用my_alloc函数分配的内存都自动记录在一个指针数组mempool中,这个数组在程序运行时首先初始化,每次调用my_alloc函数,都将分配的内存指针记录在mempool中,在程序运行结束前将mempool中记录的内存指针依次释放,最后将mempool释放,如此操作,用户只需调用my_alloc分配内存就可以了,不必顾及其他问题。

自定义静态变量和相关函数,测试一下分配1000次内存

  • #define PAGESIZE 128 定义宏PAGESIZE每次为mempool增加128个指针
  • static void **mempool = NULL; 无类型指针数组,保存分配的内存指针
  • static int pcount = 0; 记录分配内存的次数,每次加一
  • static int ps = 1; 记录mempool重新分配内存的次数
  • xmalloc函数,调用malloc分配内存,如出错则显示信息并返回NULL!!!
  • my_mempool_init函数,初始化mempool,为无类型指针数组分配128个指针!
  • my_alloc函数,分配内存,保存内存指针,记录次数,等于ps*PAGESIZE则ps增一,重新为mempool分配内存!!!
  • my_mempool_free函数,释放所有分配的内存
  • my_mempool_out_info函数,输出mempool相关的信息
  • my_strlen函数,自定义求字符串长度的函数
  • my_strdup函数,自定义字符串复制函数,返回复制的字符串的指针,这个指针是用myalloc在内存中分配的,只需要在程序运行结束前用my_mempool_free统一释放就可以了。

代码如下:

/* filename: mem.c */
#include <stdio.h>
#include <stdlib.h>

/**/
#define PAGESIZE 128

/**/
static void **mempool = NULL;
static int pcount = 0;
static int ps = 1;

/* */
static void *
xmalloc (size_t size)
{
  void *value = malloc (size);
  if (value == NULL)
    fprintf (stderr, "Alloc Memory error!\n");
  return value;
}

/**/
void
my_mempool_init (void)
{
  mempool = xmalloc (ps * PAGESIZE * sizeof(void*));
}

/**/
void*
my_alloc (int len)
{
  void *tmp = xmalloc (len);
  mempool[pcount] = tmp;
  pcount = pcount + 1;
  if (ps * PAGESIZE == pcount)
    {
      ps = ps + 1;
      mempool = realloc (mempool, ps * PAGESIZE * sizeof(void*));
    }
  return tmp;
}

/**/
void
my_mempool_free (void)
{
  for (int i = 0; i < pcount; i++)
    free (mempool[i]);
  free (mempool);
}

/**/
void
my_mempool_out_info (void)
{
  printf ("PAGESIZE : %d\n", PAGESIZE);
  printf ("Count : %d\n", pcount);
  printf ("Pages : %d\n", ps);
  printf ("Pointers : %d\n", ps * PAGESIZE);
}

/**/
int
my_strlen (char *str)
{
  int len = 0;
  while (*str != 0)
    {
      len = len + 1;
      str++;
    }
  return len;
}

/**/
char*
my_strdup (char *str)
{
  int len = my_strlen (str);
  char *tmp = (char*) my_alloc (len * sizeof(char));
  for (int i = 0; i < len; i++)
    tmp[i] = str[i];
  return tmp;
}

/**/
int
main (int argc, char *argv[])
{
  my_mempool_init ();
  for (int j = 0; j < 1000; j++)
    {
      char *tmp = my_strdup ("Not only a test here!");
    }
  my_mempool_out_info ();
  my_mempool_free ();
  return 0;
}
/* --(.v.)-- */

编译运行,通过,再用valgrind来检测一下,结果如下:

songvm@ubuntu:~/works/xdn/moo$ gcc mem.c -o mem
songvm@ubuntu:~/works/xdn/moo$ ./mem
PAGESIZE : 128
Count : 1000
Pages : 8
Pointers : 1024
songvm@ubuntu:~/works/xdn/moo$ valgrind --leak-check=yes ./mem
==3835== Memcheck, a memory error detector
==3835== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3835== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==3835== Command: ./mem
==3835== 
PAGESIZE : 128
Count : 1000
Pages : 8
Pointers : 1024
==3835== 
==3835== HEAP SUMMARY:
==3835==     in use at exit: 0 bytes in 0 blocks
==3835==   total heap usage: 1,009 allocs, 1,009 frees, 58,888 bytes allocated
==3835== 
==3835== All heap blocks were freed -- no leaks are possible
==3835== 
==3835== For counts of detected and suppressed errors, rerun with: -v
==3835== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

将mempool封装到一个结构体中去

  • 以上代码用到三个静态变量mempool, pcount, ps,用struct _Mempool结构体封装起来更规范一些!!!
  • 再定义一个静态的结构体变量 static Mempool _mempool; 供程序调用。

修改代码如下:

/* filename: mema.c */
#include <stdio.h>
#include <stdlib.h>

/**/
#define PAGESIZE 128

/*
static void **mempool = NULL;
static int pcount = 0;
static int ps = 1;
*/

/**/
typedef struct _Mempool Mempool;
struct _Mempool {
  void **pool;
  int pcount, ps;
};

/**/
static Mempool _mempool;

/**/
static void *
xmalloc (size_t size)
{
  void *value = malloc (size);
  if (value == NULL)
    fprintf (stderr, "Alloc Memory error!\n");
  return value;
}

/**/
static Mempool *
get_mempool (void)
{
  return &_mempool;
}

/**/
void
my_mempool_init (Mempool *mem)
{
  mem->pcount = 0;
  mem->ps = 1;
  mem->pool = xmalloc (mem->ps * PAGESIZE * sizeof(void*));
}

/**/
void*
my_alloc (int len)
{
  Mempool *mem = get_mempool();
  void *tmp = xmalloc (len);
  mem->pool[mem->pcount] = tmp;
  mem->pcount = mem->pcount + 1;
  if (((mem->ps) * PAGESIZE) == (mem->pcount))
    {
      mem->ps = mem->ps + 1;
      mem->pool = realloc (mem->pool, ((mem->ps) * PAGESIZE) * sizeof(void*));
    }
  return tmp;
}

/**/
void
my_mempool_free (Mempool *mem)
{
  for (int i = 0; i < mem->pcount; i++)
    free (mem->pool[i]);
  free (mem->pool);
}

/**/
void
my_mempool_out_info (Mempool *mem)
{
  printf ("PAGESIZE : %d\n", PAGESIZE);
  printf ("Count : %d\n", mem->pcount);
  printf ("Pages : %d\n", mem->ps);
  printf ("Pointers : %d\n", (mem->ps) * PAGESIZE);
}

/**/
int
my_strlen (char *str)
{
  int len = 0;
  while (*str != 0)
    {
      len = len + 1;
      str++;
    }
  return len;
}

/**/
char*
my_strdup (char *str)
{
  int len = my_strlen (str);
  char *tmp = (char*) my_alloc (len * sizeof(char));
  for (int i = 0; i < len; i++)
    tmp[i] = str[i];
  return tmp;
}

/**/
int
main (int argc, char *argv[])
{
  Mempool *mem = get_mempool ();
  my_mempool_init (mem);
  for (int j = 0; j < 1000; j++)
    {
      char *tmp = my_strdup ("Not only a test here!");
    }
  my_mempool_out_info (mem);
  my_mempool_free (mem);
  return 0;
}
/* --(.v.)-- */

编译运行,用valgrind检查一下有无内存泄漏情况,结果如下:

songvm@ubuntu:~/works/xdn/moo$ gcc mema.c -o mema
songvm@ubuntu:~/works/xdn/moo$ ./mema
PAGESIZE : 128
Count : 1000
Pages : 8
Pointers : 1024
songvm@ubuntu:~/works/xdn/moo$ valgrind --leak-check=yes ./mema
==3913== Memcheck, a memory error detector
==3913== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3913== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==3913== Command: ./mema
==3913== 
PAGESIZE : 128
Count : 1000
Pages : 8
Pointers : 1024
==3913== 
==3913== HEAP SUMMARY:
==3913==     in use at exit: 0 bytes in 0 blocks
==3913==   total heap usage: 1,009 allocs, 1,009 frees, 58,888 bytes allocated
==3913== 
==3913== All heap blocks were freed -- no leaks are possible
==3913== 
==3913== For counts of detected and suppressed errors, rerun with: -v
==3913== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
songvm@ubuntu:~/works/xdn/moo$

再分配1000个整数的数组指针并赋值测试,同时加上简单的注释

代码如下:

/* filename: memb.c */
#include <stdio.h>
#include <stdlib.h>

/* compile : gcc memb.c -o memb
       run : ./memb
   memcheck: valgrind --leak-check=yes ./memb  */

/**/
#define PAGESIZE 128

/* define Mempool datatype */
typedef struct _Mempool Mempool;
struct _Mempool {
  void **pool;
  int pcount, ps;
};

/* the mempool here! */
static Mempool _mempool;

/* call malloc function and out error info */
static void *
xmalloc (size_t size)
{
  void *value = malloc (size);
  if (value == NULL)
    fprintf (stderr, "Alloc Memory error!\n");
  return value;
}

/* got the mempool! */
static Mempool *
get_mempool (void)
{
  return &_mempool;
}

/* init the mempool */
void
my_mempool_init (Mempool *mem)
{
  mem->pcount = 0;
  mem->ps = 1;
  mem->pool = xmalloc (mem->ps * PAGESIZE * sizeof(void*));
}

/* define alloc function myself */
void*
my_alloc (int len)
{
  Mempool *mem = get_mempool();
  void *tmp = xmalloc (len);
  mem->pool[mem->pcount] = tmp;
  mem->pcount = mem->pcount + 1;
  if (((mem->ps) * PAGESIZE) == (mem->pcount))
    {
      mem->ps = mem->ps + 1;
      mem->pool = realloc (mem->pool, ((mem->ps) * PAGESIZE) * sizeof(void*));
    }
  return tmp;
}

/* define free function myself */
void
my_mempool_free (Mempool *mem)
{
  for (int i = 0; i < mem->pcount; i++)
    free (mem->pool[i]);
  free (mem->pool);
}

/* output mempool info */
void
my_mempool_out_info (Mempool *mem)
{
  printf ("PAGESIZE : %d\n", PAGESIZE);
  printf ("Count : %d\n", mem->pcount);
  printf ("Pages : %d\n", mem->ps);
  printf ("Pointers : %d\n", (mem->ps) * PAGESIZE);
}

/* define strlen funcfion myself */
int
my_strlen (char *str)
{
  int len = 0;
  while (*str != 0)
    {
      len = len + 1;
      str++;
    }
  return len;
}

/* define strdup function myself return the str pointer
   without free, my_mempool_free will free all */
char*
my_strdup (char *str)
{
  int len = my_strlen (str);
  char *tmp = (char*) my_alloc (len * sizeof(char));
  for (int i = 0; i < len; i++)
    tmp[i] = str[i];
  return tmp;
}

/* ------------------------- */

/**/
int
main (int argc, char *argv[])
{
  Mempool *mem = get_mempool ();

  my_mempool_init (mem);

  for (int j = 0; j < 1000; j++)
    {
      char *tmp = my_strdup ("Not only a test here!");
    }
  my_mempool_out_info (mem);
  printf ("--------------------\n");

  int *ip = (int*) my_alloc (1000 * sizeof(int));
  for (int k = 0; k < 1000; k++)
    ip[k] = k;
  my_mempool_out_info (mem);
  printf ("--------------------\n");

  my_mempool_free (mem);
  return 0;
}
/* --(.v.)-- */

编译运行,达到预期效果

songvm@ubuntu:~/works/xdn/moo$ gcc memb.c -o memb
songvm@ubuntu:~/works/xdn/moo$ ./memb
PAGESIZE : 128
Count : 1000
Pages : 8
Pointers : 1024
--------------------
PAGESIZE : 128
Count : 1001
Pages : 8
Pointers : 1024
--------------------
songvm@ubuntu:~/works/xdn/moo$ valgrind --leak-check=yes ./memb
==3944== Memcheck, a memory error detector
==3944== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3944== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==3944== Command: ./memb
==3944== 
PAGESIZE : 128
Count : 1000
Pages : 8
Pointers : 1024
--------------------
PAGESIZE : 128
Count : 1001
Pages : 8
Pointers : 1024
--------------------
==3944== 
==3944== HEAP SUMMARY:
==3944==     in use at exit: 0 bytes in 0 blocks
==3944==   total heap usage: 1,010 allocs, 1,010 frees, 62,888 bytes allocated
==3944== 
==3944== All heap blocks were freed -- no leaks are possible
==3944== 
==3944== For counts of detected and suppressed errors, rerun with: -v
==3944== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
songvm@ubuntu:~/works/xdn/moo$

分成多个文件编译,为开发大一点的应用做准备

头文件mem.h代码如下:

/* filename: mem.h */
#ifndef MEM_HEADER
#define MEM_HEADER

/**/
#define PAGESIZE 128

/* define Mempool datatype */
typedef struct _Mempool Mempool;
struct _Mempool {
  void **pool;
  int pcount, ps;
};

Mempool * get_mempool (void);
void my_mempool_init (Mempool *mem);
void * my_alloc (int len);
void my_mempool_free (Mempool *mem);
void my_mempool_out_info (Mempool *mem);

int my_strlen (char *str);
char * my_strdup (char *str);

#endif/*MEM_HEADER*/

*相关功能实现mem.c代码如下:

/* filename: mem.c */
#include <stdio.h>
#include <stdlib.h>
#include "mem.h"

/* the mempool here! */
static Mempool _mempool;

/* call malloc function and out error info */
static void *
xmalloc (size_t size)
{
  void *value = malloc (size);
  if (value == NULL)
    fprintf (stderr, "Alloc Memory error!\n");
  return value;
}

/* got the mempool! */
Mempool *
get_mempool (void)
{
  return &_mempool;
}

/* init the mempool */
void
my_mempool_init (Mempool *mem)
{
  mem->pcount = 0;
  mem->ps = 1;
  mem->pool = xmalloc (mem->ps * PAGESIZE * sizeof(void*));
}

/* define alloc function myself */
void*
my_alloc (int len)
{
  Mempool *mem = get_mempool();
  void *tmp = xmalloc (len);
  mem->pool[mem->pcount] = tmp;
  mem->pcount = mem->pcount + 1;
  if (((mem->ps) * PAGESIZE) == (mem->pcount))
    {
      mem->ps = mem->ps + 1;
      mem->pool = realloc (mem->pool, ((mem->ps) * PAGESIZE) * sizeof(void*));
    }
  return tmp;
}

/* define free function myself */
void
my_mempool_free (Mempool *mem)
{
  for (int i = 0; i < mem->pcount; i++)
    free (mem->pool[i]);
  free (mem->pool);
}

/* output mempool info */
void
my_mempool_out_info (Mempool *mem)
{
  printf ("PAGESIZE : %d\n", PAGESIZE);
  printf ("Count : %d\n", mem->pcount);
  printf ("Pages : %d\n", mem->ps);
  printf ("Pointers : %d\n", (mem->ps) * PAGESIZE);
}

/* define strlen funcfion myself */
int
my_strlen (char *str)
{
  int len = 0;
  while (*str != 0)
    {
      len = len + 1;
      str++;
    }
  return len;
}

/* define strdup function myself return the str pointer
   without free, my_mempool_free will free all */
char*
my_strdup (char *str)
{
  int len = my_strlen (str);
  char *tmp = (char*) my_alloc (len * sizeof(char));
  for (int i = 0; i < len; i++)
    tmp[i] = str[i];
  return tmp;
}
/* ----- mem.c ----- */
  • 测试功能文件tmem.c代码如下:
/* filename: tmem.c */
#include <stdio.h>
#include <stdlib.h>
#include "mem.h"

/* compile : gcc mem.c tmem.c -o tmem
       run : ./tmem
   memcheck: vargrind --leak-check=yes ./tmem  */

/**/
int
main (int argc, char *argv[])
{
  Mempool *mem = get_mempool ();

  my_mempool_init (mem);

  for (int j = 0; j < 1000; j++)
    {
      char *tmp = my_strdup ("Not only a test here!");
    }
  my_mempool_out_info (mem);
  printf ("--------------------\n");

  int *ip = (int*) my_alloc (1000 * sizeof(int));
  for (int k = 0; k < 1000; k++)
    ip[k] = k;
  my_mempool_out_info (mem);
  printf ("--------------------\n");

  my_mempool_free (mem);
  return 0;
}
/* --(.v.)-- */

编译运行,结果如预期:

gwsong@ubuntu:~/works/zoo/moo$ gcc mem.c tmem.c -o tmem
gwsong@ubuntu:~/works/zoo/moo$ ls
memb  memb.c  mem.c  mem.c~  mem.h  mem.h~  tmem  tmem.c  tmem.c~
gwsong@ubuntu:~/works/zoo/moo$ ./tmem
PAGESIZE : 128
Count : 1000
Pages : 8
Pointers : 1024
--------------------
PAGESIZE : 128
Count : 1001
Pages : 8
Pointers : 1024
--------------------
gwsong@ubuntu:~/works/zoo/moo$ valgrind --leak-check=yes ./tmem
==3639== Memcheck, a memory error detector
==3639== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3639== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==3639== Command: ./tmem
==3639== 
PAGESIZE : 128
Count : 1000
Pages : 8
Pointers : 1024
--------------------
PAGESIZE : 128
Count : 1001
Pages : 8
Pointers : 1024
--------------------
==3639== 
==3639== HEAP SUMMARY:
==3639==     in use at exit: 0 bytes in 0 blocks
==3639==   total heap usage: 1,010 allocs, 1,010 frees, 62,888 bytes allocated
==3639== 
==3639== All heap blocks were freed -- no leaks are possible
==3639== 
==3639== For counts of detected and suppressed errors, rerun with: -v
==3639== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
gwsong@ubuntu:~/works/zoo/moo$ 

下一步研究一下数据结构!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值