keepalived源码浅析——Memory 内存管理

本文详细介绍了Memory模块的功能,包括内存分配和释放的封装,以及在debug模式下如何通过打印文件名、函数名等信息来帮助定位内存泄漏的位置。此外,还提供了Memory模块中关键函数如malloc、free和realloc的具体实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Memory模块的作用:封装了内存申请和释放函数,打印文件、函数、申请内存大小、代码行数等信息,dubug模式下定位内存泄露位置。

Memory.h源码:

#ifndef _MEMORY_H
#define _MEMORY_H

/* system includes */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

/* extern types */
extern unsigned long mem_allocated;
extern void *xalloc(unsigned long size);
extern void *zalloc(unsigned long size);
extern void xfree(void *p);

/* Global alloc macro */
#define ALLOC(n) (xalloc(n))

/* Local defines */
#ifdef _DEBUG_

#define MAX_ALLOC_LIST 2048

#define MALLOC(n)    ( keepalived_malloc((n), \
                      (__FILE__), (char *)(__FUNCTION__), (__LINE__)) )
#define FREE(b)      ( keepalived_free((b), \
                      (__FILE__), (char *)(__FUNCTION__), (__LINE__)) )
#define REALLOC(b,n) ( keepalived_realloc((b), (n), \
                      (__FILE__), (char *)(__FUNCTION__), (__LINE__)) )

/* Memory debug prototypes defs */
extern char *keepalived_malloc(unsigned long, char *, char *, int);
extern int keepalived_free(void *, char *, char *, int);
extern void *keepalived_realloc(void *, unsigned long, char *, char *, int);
extern void keepalived_free_final(char *);

#else

#define MALLOC(n)    (zalloc(n))
#define FREE(p)      (xfree(p))
#define REALLOC(p,n) (realloc((p),(n)))

#endif

/* Common defines */
#define FREE_PTR(P) if((P)) FREE((P));

#endif

 


 

Memory.c源码:

#include "memory.h"
#include "utils.h"

/* Global var */
unsigned long mem_allocated;	/* Total memory used in Bytes */

void *
xalloc(unsigned long size)
{
	void *mem;
	if ((mem = malloc(size)))
		mem_allocated += size;
	return mem;
}

void *
zalloc(unsigned long size)
{
	void *mem;
	if ((mem = malloc(size))) {
		memset(mem, 0, size);
		mem_allocated += size;
	}
	return mem;
}

void
xfree(void *p)
{
	mem_allocated -= sizeof (p);
	free(p);
	p = NULL;
}

/* KeepAlived memory management. in debug mode,
 * help finding eventual memory leak.
 * Allocation memory types manipulated are :        //内存泄露类型
 *
 * +type+--------meaning--------+
 * ! 0  ! Free slot             !
 * ! 1  ! Overrun               !
 * ! 2  ! free null             !
 * ! 3  ! realloc null          !
 * ! 4  ! Not previus allocated !
 * ! 8  ! Last free list        !
 * ! 9  ! Allocated             !
 * +----+-----------------------+
 *
 * global variabel debug bit 9 ( 512 ) used to
 * flag some memory error.
 *
 */

#ifdef _DEBUG_

typedef struct {
	int type;
	int line;
	char *func;
	char *file;
	void *ptr;
	unsigned long size;
	long csum;
} MEMCHECK;

/* Last free pointers */
static MEMCHECK free_list[256];

static MEMCHECK alloc_list[MAX_ALLOC_LIST];  //结构体数组
static int number_alloc_list = 0;
static int n = 0;		/* Alloc list pointer */
static int f = 0;		/* Free list pointer */

char *
keepalived_malloc(unsigned long size, char *file, char *function, int line) //内存申请
{
	void *buf;
	int i = 0;
	long check;

	buf = zalloc(size + sizeof (long));

	check = 0xa5a5 + size;
	*(long *) ((char *) buf + size) = check;

	while (i < number_alloc_list) {
		if (alloc_list[i].type == 0)
			break;
		i++;
	}

	if (i == number_alloc_list)
		number_alloc_list++;

	assert(number_alloc_list < MAX_ALLOC_LIST);

	alloc_list[i].ptr = buf;
	alloc_list[i].size = size;
	alloc_list[i].file = file;
	alloc_list[i].func = function;
	alloc_list[i].line = line;
	alloc_list[i].csum = check;
	alloc_list[i].type = 9;

	if (debug & 1)
		printf("zalloc[%3d:%3d], %p, %4ld at %s, %3d, %s\n",
		       i, number_alloc_list, buf, size, file, line,
		       function);

	n++;
	return buf;
}

int
keepalived_free(void *buffer, char *file, char *function, int line)  //内存释放
{
	int i = 0;
	void *buf;

	/* If nullpointer remember */
	if (buffer == NULL) {
		i = number_alloc_list++;

		assert(number_alloc_list < MAX_ALLOC_LIST);

		alloc_list[i].ptr = buffer;
		alloc_list[i].size = 0;
		alloc_list[i].file = file;
		alloc_list[i].func = function;
		alloc_list[i].line = line;
		alloc_list[i].type = 2;
		if (debug & 1)
			printf("free NULL in %s, %3d, %s\n", file,
			       line, function);

		debug |= 512;	/* Memory Error detect */

		return n;
	} else
		buf = buffer;

	while (i < number_alloc_list) {
		if (alloc_list[i].type == 9 && alloc_list[i].ptr == buf) {
			if (*
			    ((long *) ((char *) alloc_list[i].ptr +
				       alloc_list[i].size)) ==
			    alloc_list[i].csum)
				alloc_list[i].type = 0;	/* Release */
			else {
				alloc_list[i].type = 1;	/* Overrun */
				if (debug & 1) {
					printf("free corrupt, buffer overrun [%3d:%3d], %p, %4ld at %s, %3d, %s\n",
					       i, number_alloc_list,
					       buf, alloc_list[i].size, file,
					       line, function);
					dump_buffer(alloc_list[i].ptr,
						    alloc_list[i].size + sizeof (long));
					printf("Check_sum\n");
					dump_buffer((char *) &alloc_list[i].csum,
						    sizeof(long));

					debug |= 512;	/* Memory Error detect */
				}
			}
			break;
		}
		i++;
	}

	/*  Not found */
	if (i == number_alloc_list) {
		printf("Free ERROR %p\n", buffer);
		number_alloc_list++;

		assert(number_alloc_list < MAX_ALLOC_LIST);

		alloc_list[i].ptr = buf;
		alloc_list[i].size = 0;
		alloc_list[i].file = file;
		alloc_list[i].func = function;
		alloc_list[i].line = line;
		alloc_list[i].type = 4;
		debug |= 512;

		return n;
	}

	if (buffer != NULL)
		xfree(buffer);

	if (debug & 1)
		printf("free  [%3d:%3d], %p, %4ld at %s, %3d, %s\n",
		       i, number_alloc_list, buf,
		       alloc_list[i].size, file, line, function);

	free_list[f].file = file;
	free_list[f].line = line;
	free_list[f].func = function;
	free_list[f].ptr = buffer;
	free_list[f].type = 8;
	free_list[f].csum = i;	/* Using this field for row id */

	f++;
	f &= 255;
	n--;

	return n;
}

void
keepalived_free_final(char *banner) //定位内存泄露位置
{
	unsigned int sum = 0, overrun = 0, badptr = 0;
	int i, j;
	i = 0;

	printf("\n---[ Keepalived memory dump for (%s)]---\n\n", banner);

	while (i < number_alloc_list) {
		switch (alloc_list[i].type) {
		case 3:
			badptr++;
			printf
			    ("null pointer to realloc(nil,%ld)! at %s, %3d, %s\n",
			     alloc_list[i].size, alloc_list[i].file,
			     alloc_list[i].line, alloc_list[i].func);
			break;
		case 4:
			badptr++;
			printf
			    ("pointer not found in table to free(%p) [%3d:%3d], at %s, %3d, %s\n",
			     alloc_list[i].ptr, i, number_alloc_list,
			     alloc_list[i].file, alloc_list[i].line,
			     alloc_list[i].func);
			for (j = 0; j < 256; j++)
				if (free_list[j].ptr == alloc_list[i].ptr)
					if (free_list[j].type == 8)
						printf
						    ("  -> pointer allready released at [%3d:%3d], at %s, %3d, %s\n",
						     (int) free_list[j].csum,
						     number_alloc_list,
						     free_list[j].file,
						     free_list[j].line,
						     free_list[j].func);
			break;
		case 2:
			badptr++;
			printf("null pointer to free(nil)! at %s, %3d, %s\n",
			       alloc_list[i].file, alloc_list[i].line,
			       alloc_list[i].func);
			break;
		case 1:
			overrun++;
			printf("%p [%3d:%3d], %4ld buffer overrun!:\n",
			       alloc_list[i].ptr, i, number_alloc_list,
			       alloc_list[i].size);
			printf(" --> source of malloc: %s, %3d, %s\n",
			       alloc_list[i].file, alloc_list[i].line,
			       alloc_list[i].func);
			break;
		case 9:
			sum += alloc_list[i].size;
			printf("%p [%3d:%3d], %4ld not released!:\n",
			       alloc_list[i].ptr, i, number_alloc_list,
			       alloc_list[i].size);
			printf(" --> source of malloc: %s, %3d, %s\n",
			       alloc_list[i].file, alloc_list[i].line,
			       alloc_list[i].func);
			break;
		}
		i++;
	}

	printf("\n\n---[ Keepalived memory dump summary for (%s) ]---\n", banner);
	printf("Total number of bytes not freed...: %d\n", sum);
	printf("Number of entries not freed.......: %d\n", n);
	printf("Maximum allocated entries.........: %d\n", number_alloc_list);
	printf("Number of bad entries.............: %d\n", badptr);
	printf("Number of buffer overrun..........: %d\n\n", overrun);

	if (sum || n || badptr || overrun)
		printf("=> Program seems to have some memory problem !!!\n\n");
	else
		printf("=> Program seems to be memory allocation safe...\n\n");
}

void *
keepalived_realloc(void *buffer, unsigned long size, char *file, char *function,
		   int line)
{
	int i = 0;
	void *buf, *buf2;
	long check;

	if (buffer == NULL) {
		printf("realloc %p %s, %3d %s\n", buffer, file, line, function);
		i = number_alloc_list++;

		assert(number_alloc_list < MAX_ALLOC_LIST);

		alloc_list[i].ptr = NULL;
		alloc_list[i].size = 0;
		alloc_list[i].file = file;
		alloc_list[i].func = function;
		alloc_list[i].line = line;
		alloc_list[i].type = 3;
		return keepalived_malloc(size, file, function, line);
	}

	buf = buffer;

	while (i < number_alloc_list) {
		if (alloc_list[i].ptr == buf) {
			buf = alloc_list[i].ptr;
			break;
		}
		i++;
	}

	/* not found */
	if (i == number_alloc_list) {
		printf("realloc ERROR no matching zalloc %p \n", buffer);
		number_alloc_list++;

		assert(number_alloc_list < MAX_ALLOC_LIST);

		alloc_list[i].ptr = buf;
		alloc_list[i].size = 0;
		alloc_list[i].file = file;
		alloc_list[i].func = function;
		alloc_list[i].line = line;
		alloc_list[i].type = 9;
		debug |= 512;	/* Memory Error detect */
		return NULL;
	}

	buf2 = ((char *) buf) + alloc_list[i].size;

	if (*(long *) (buf2) != alloc_list[i].csum) {
		alloc_list[i].type = 1;
		debug |= 512;	/* Memory Error detect */
	}
	buf = realloc(buffer, size + sizeof (long));

	check = 0xa5a5 + size;
	*(long *) ((char *) buf + size) = check;
	alloc_list[i].csum = check;

	if (debug & 1)
		printf("realloc [%3d:%3d] %p, %4ld %s %d %s -> %p %4ld %s %d %s\n",
		       i, number_alloc_list, alloc_list[i].ptr,
		       alloc_list[i].size, file, line, function, buf, size,
		       alloc_list[i].file, alloc_list[i].line,
		       alloc_list[i].func);

	alloc_list[i].ptr = buf;
	alloc_list[i].size = size;
	alloc_list[i].file = file;
	alloc_list[i].line = line;
	alloc_list[i].func = function;

	return buf;
}

#endif



调用位置

main.c中的stop_keepalived函数

#ifdef _DEBUG_
	keepalived_free_final("Parent process");
#endif


check_daemon.c中的stop_check函数

#ifdef _DEBUG_
 keepalived_free_final("Healthcheck child process");
#endif



 

vrrp_daemon.c中的stop_vrrp函数

#ifdef _DEBUG_
	keepalived_free_final("VRRP Child process");
#endif



 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值