Add memalloc for testing memory operations.

This commit is contained in:
zhengshuxin 2024-06-23 18:04:08 +08:00
parent 279301f6bf
commit ef3982d66b
4 changed files with 187 additions and 8 deletions

View File

@ -19,11 +19,9 @@ CFLAGS = -c -g -W \
########################################################### ###########################################################
#Check system: #Check system:
SYSLIB =
CHECKSYSRES = @echo "Unknow system type!";exit 1 CHECKSYSRES = @echo "Unknow system type!";exit 1
UNIXNAME = $(shell uname -sm) UNIXNAME = $(shell uname -sm)
UNIXTYPE = LINUX shared_ldflags =
polarssl =
ifeq ($(CC),) ifeq ($(CC),)
CC = g++ CC = g++
@ -42,6 +40,17 @@ ifeq ($(findstring clang++, $(CC)), clang++)
-Wno-invalid-offsetof -Wno-invalid-offsetof
endif endif
# For Linux
ifeq ($(findstring Linux, $(UNIXNAME)), Linux)
shared_ldflags += -lunwind -lunwind-x86_64 -lz -lpthread
endif
# For Darwin
ifeq ($(findstring Darwin, $(UNIXNAME)), Darwin)
CFLAGS += -D_XOPEN_SOURCE -Wno-deprecated-declarations
shared_ldflags += -lz -lpthread
endif
#Find system type. #Find system type.
ifneq ($(SYSPATH),) ifneq ($(SYSPATH),)
CHECKSYSRES = @echo "System is $(shell uname -sm)" CHECKSYSRES = @echo "System is $(shell uname -sm)"
@ -53,7 +62,6 @@ LIB_PATH_DST = .
DEF_PATH_DST = ./debug DEF_PATH_DST = ./debug
CFLAGS += -I. CFLAGS += -I.
shared_ldflags = -lunwind -lunwind-x86_64 -lz -lpthread
#Project's objs #Project's objs
OBJS_DST = $(patsubst %.cpp, $(OBJ_PATH_DST)/%.o, $(notdir $(wildcard ./*.cpp))) OBJS_DST = $(patsubst %.cpp, $(OBJ_PATH_DST)/%.o, $(notdir $(wildcard ./*.cpp)))

View File

@ -3,7 +3,9 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <ucontext.h>
#include <libunwind.h> #include <libunwind.h>
#include "libmm.h"
static void stacktrace(void) static void stacktrace(void)
{ {
@ -35,8 +37,6 @@ static void stacktrace(void)
} }
} }
typedef void *(*malloc_fn)(size_t);
static malloc_fn __malloc_fn = NULL;
static size_t total_size = 0; static size_t total_size = 0;
static bool __check = false; static bool __check = false;
static pthread_mutex_t __lock; static pthread_mutex_t __lock;
@ -45,7 +45,6 @@ static pthread_once_t once_control = PTHREAD_ONCE_INIT;
static void once_init(void) static void once_init(void)
{ {
__malloc_fn = (malloc_fn) dlsym(RTLD_NEXT, "malloc");
pthread_mutex_init(&__lock, NULL); pthread_mutex_init(&__lock, NULL);
} }
@ -69,7 +68,7 @@ void *malloc(size_t size)
return NULL; return NULL;
} }
ptr = __malloc_fn(size); ptr = mymalloc(size);
if (ptr && __check) { if (ptr && __check) {
if (size == 8208) { if (size == 8208) {
//abort(); //abort();

View File

@ -5,6 +5,9 @@
extern "C" { extern "C" {
#endif #endif
void *mymalloc(size_t size);
void print_mem_list();
//void start_check(void); //void start_check(void);
//void stop_check(void); //void stop_check(void);

169
test/libmm/memalloc.cpp Normal file
View File

@ -0,0 +1,169 @@
#include <unistd.h>
#include <string.h>
#include <pthread.h>
// Copy from https://github.com/arjun024/memalloc
/* Only for the debug printf */
#include <stdio.h>
#include "libmm.h"
typedef char ALIGN[16];
union header {
struct {
size_t size;
unsigned is_free;
union header *next;
} s;
/* force the header to be aligned to 16 bytes */
ALIGN stub;
};
typedef union header header_t;
header_t *head = NULL, *tail = NULL;
pthread_mutex_t global_malloc_lock;
static header_t *get_free_block(size_t size)
{
header_t *curr = head;
while(curr) {
/* see if there's a free block that can accomodate requested size */
if (curr->s.is_free && curr->s.size >= size)
return curr;
curr = curr->s.next;
}
return NULL;
}
void free(void *block)
{
header_t *header, *tmp;
/* program break is the end of the process's data segment */
void *programbreak;
if (!block)
return;
pthread_mutex_lock(&global_malloc_lock);
header = (header_t*)block - 1;
/* sbrk(0) gives the current program break address */
programbreak = sbrk(0);
/*
Check if the block to be freed is the last one in the
linked list. If it is, then we could shrink the size of the
heap and release memory to OS. Else, we will keep the block
but mark it as free.
*/
if ((char*)block + header->s.size == programbreak) {
if (head == tail) {
head = tail = NULL;
} else {
tmp = head;
while (tmp) {
if(tmp->s.next == tail) {
tmp->s.next = NULL;
tail = tmp;
}
tmp = tmp->s.next;
}
}
/*
sbrk() with a negative argument decrements the program break.
So memory is released by the program to OS.
*/
sbrk(0 - header->s.size - sizeof(header_t));
/* Note: This lock does not really assure thread
safety, because sbrk() itself is not really
thread safe. Suppose there occurs a foregin sbrk(N)
after we find the program break and before we decrement
it, then we end up realeasing the memory obtained by
the foreign sbrk().
*/
pthread_mutex_unlock(&global_malloc_lock);
return;
}
header->s.is_free = 1;
pthread_mutex_unlock(&global_malloc_lock);
}
void *mymalloc(size_t size)
{
size_t total_size;
void *block;
header_t *header;
if (!size)
return NULL;
pthread_mutex_lock(&global_malloc_lock);
header = get_free_block(size);
if (header) {
/* Woah, found a free block to accomodate requested memory. */
header->s.is_free = 0;
pthread_mutex_unlock(&global_malloc_lock);
return (void*)(header + 1);
}
/* We need to get memory to fit in the requested block and header from OS. */
total_size = sizeof(header_t) + size;
block = sbrk(total_size);
if (block == (void*) -1) {
pthread_mutex_unlock(&global_malloc_lock);
return NULL;
}
header = (header_t*) block;
header->s.size = size;
header->s.is_free = 0;
header->s.next = NULL;
if (!head)
head = header;
if (tail)
tail->s.next = header;
tail = header;
pthread_mutex_unlock(&global_malloc_lock);
return (void*)(header + 1);
}
void *calloc(size_t num, size_t nsize)
{
size_t size;
void *block;
if (!num || !nsize)
return NULL;
size = num * nsize;
/* check mul overflow */
if (nsize != size / num)
return NULL;
block = mymalloc(size);
if (!block)
return NULL;
memset(block, 0, size);
return block;
}
void *realloc(void *block, size_t size)
{
header_t *header;
void *ret;
if (!block || !size)
return mymalloc(size);
header = (header_t*)block - 1;
if (header->s.size >= size)
return block;
ret = mymalloc(size);
if (ret) {
/* Relocate contents to the new bigger block */
memcpy(ret, block, header->s.size);
/* Free the old memory block */
free(block);
}
return ret;
}
/* A debug function to print the entire link list */
void print_mem_list()
{
header_t *curr = head;
printf("head = %p, tail = %p \n", (void*)head, (void*)tail);
while(curr) {
printf("addr = %p, size = %zu, is_free=%u, next=%p\n",
(void*)curr, curr->s.size, curr->s.is_free, (void*)curr->s.next);
curr = curr->s.next;
}
}