0%

What is different with malloc and sbrk

I was refactoring the project because sometimes the project crashed. Analyzing the code I found it is the problem of memory managemnt. Sometime it use the wrong address when it free the memory. In the project, it didn’t use malloc of GNU C library to allocate the memory and it implemented the feature.

The following code is a basiclly malloc implementation from stackoverflow. It use sbrk to implement malloc. I was confusing why it use a low-level function to implement malloc allocating the memory. What is different with malloc and sbrk?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void* malloc(size_t size) {
size = (size + sizeof(size_t) + (align_to - 1)) & ~ (align_to - 1);
free_block* block = free_block_list_head.next;
free_block** head = &(free_block_list_head.next);
while (block != 0) {
if (block->size >= size) {
*head = block->next;
return ((char*)block) + sizeof(size_t);
}
head = &(block->next);
block = block->next;
}

block = (free_block*)sbrk(size);
block->size = size;

return ((char*)block) + sizeof(size_t);
}

What is different with malloc and sbrk?

sbrk is a low-level function in GNU C library. From wikipedia said that brk and sbrk are basic memory management system calls used in Unix and Unix-like operating systems to control the amount of memory allocated to the data segment of the process. sbrk supports to allocate the memory but it isn’t flexible to use memory that means it can’t use released memory. You can follow the code and I used static memory to refactor malloc. The code allocated a huge array and it retured the pointer address to new block if it wasn’t released memory.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#define MEM_SIZE 0x10000
static unsigned int mem_pool[MEM_SIZE];
static unsigned int offset = 0;

void* new_malloc(size_t size) {
unsigned int *p = mem_pool;
size = (size + sizeof(size_t) + (align_to - 1)) & ~ (align_to - 1);
free_block* block = free_block_list_head.next;
free_block** head = &(free_block_list_head.next);
while (block != 0) {
if (block->size >= size) {
*head = block->next;
return ((char*)block) + sizeof(size_t);
}
head = &(block->next);
block = block->next;
}

block = (free_block*)(p+offset);
block->size = size;
offset += size+1;

return ((char*)block) + sizeof(size_t);
}

Finally I can show you the implement code that what you want.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
typedef struct free_block {
size_t size;
struct free_block* next;
} free_block;

static free_block free_block_list_head = { 0, 0 };
static const size_t overhead = sizeof(size_t);
static const size_t align_to = 16;
#define MEM_SIZE 0x10000
static unsigned int mem_pool[MEM_SIZE];
static unsigned int offset = 0;

void* new_malloc(size_t size) {
unsigned int *p = mem_pool;
size = (size + sizeof(size_t) + (align_to - 1)) & ~ (align_to - 1);
free_block* block = free_block_list_head.next;
free_block** head = &(free_block_list_head.next);
while (block != 0) {
if (block->size >= size) {
*head = block->next;
return ((char*)block) + sizeof(size_t);
}
head = &(block->next);
block = block->next;
}

block = (free_block*)(p+offset);
block->size = size;
offset += size+1;

return ((char*)block) + sizeof(size_t);
}

void new_free(void* ptr) {
free_block* block = (free_block*)(((char*)ptr) - sizeof(size_t));
block->next = free_block_list_head.next;
free_block_list_head.next = block;
}

void* new_realloc(void* ptr, size_t size) {
void *new_ptr;
new_ptr = new_malloc(size);
if (new_ptr == NULL) return NULL;
memcpy(new_ptr, ptr, size);
new_free(ptr);
return new_ptr;
}