在C中创建自己的malloc函数

时间:2012-12-07 14:09:12

标签: c malloc

我需要你的帮助。我对C有一个平均的知识,这就是问题所在。我将使用一些基准来测试新处理器上的一些计算机体系结构(分支未命中,缓存未命中)。关于它的事情是基准测试在C中,但我不能包含任何库调用。例如,我不能使用malloc因为我收到了错误

"undefined reference to malloc" 

即使我已经包含了库。所以我必须编写自己的malloc。我不希望它超级高效 - 只需要做基础知识。正如我在想的那样,我必须在内存中有一个地址,并且每当malloc发生时,我都会返回一个指向该地址的指针并按该大小递增计数器。 Malloc在我的程序中发生了两次,所以我甚至不需要大容量内存。

你可以帮帮我吗?我设计了一个Verilog并且在C语言方面没有太多经验。

我见过以前的答案但对我来说似乎都太复杂了。此外,我无法访问K-R书。

干杯!

编辑:也许这可以帮到你更多: 我不是使用gcc而是使用sde-gcc编译器。它有什么不同吗?也许这就是为什么我得到一个未定义的malloc引用?

EDIT2: 我正在测试MIPS架构:

我已经包括:

#include <stdlib.h>

,错误是:

undefined reference to malloc
relocation truncated to fit: R_MIPS_26 against malloc

和编译器命令id:

test.o: test.c cap.h
sde-gcc -c -o test.s test.c -EB -march=mips64 -mabi=64 -G -O -ggdb -O2 -S
    sde-as -o test.o test.s EB -march=mips64 -mabi=64 -G -O -ggdb
    as_objects:=test.o init.o

编辑3: 好吧,我使用上面的实现,它运行没有任何问题。问题是,在进行嵌入式编程时,您只需定义所使用的所有内容,因此我定义了自己的malloc。 sde-gcc无法识别malloc函数。

4 个答案:

答案 0 :(得分:19)

这是一种非常简单的方法,可能会让你超越你的2个mallocs:

static unsigned char our_memory[1024 * 1024]; //reserve 1 MB for malloc
static size_t next_index = 0;

void *malloc(size_t sz)
{
    void *mem;

    if(sizeof our_memory - next_index < sz)
        return NULL;

    mem = &our_memory[next_index];
    next_index += sz;
    return mem;
}

void free(void *mem)
{
   //we cheat, and don't free anything.
}

如果需要,您可能需要将手背上的记忆片对齐,例如你一直 给出一个地址为4,8,16或你需要的地址的内存地址。

答案 1 :(得分:4)

尝试上面给出的一个线程安全的答案,我正在引用他的代码,如下所示:

static unsigned char our_memory[1024 * 1024]; //reserve 1 MB for malloc
static size_t next_index = 0;

static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

void *malloc(size_t sz)
{
    void *mem;
    pthread_mutex_lock(&lock);
    if(sizeof our_memory - next_index < sz){
        pthread_mutex_unlock(&lock);
        return NULL;
    }

    mem = &our_memory[next_index];
    next_index += sz;
    pthread_mutex_unlock(&lock);
    return mem;
}

void free(void *mem)
{
   //we cheat, and don't free anything.
} 

答案 2 :(得分:2)

您需要链接libc.a或系统的等效项。如果不使用标准C lib,则不会获得在main函数之前运行的任何启动代码。你的程序永远不会运行....

您可以分配一个静态数据块并在malloc的位置使用它,例如:

// char* fred = malloc(10000);
// equals

static char [100000] fred;

或者在启动时调用标准malloc以获取大块连续内存,并编写自己的malloc类型函数来将其划分。在第二种情况下,您将在调用系统的malloc之后开始基准测试,以便不影响基准测试。

答案 3 :(得分:2)

我正在分享Malloc的完整方法,并释放它在每种情况下都适用的功能。使用数组对此表示赞赏。我们还可以使用元数据的链接列表来实现。

我们必须涵盖三种情况

  1. 连续内存分配:以连续方式分配内存
  2. 两个已分配内存之间的已分配内存:当内存在两个已分配内存块之间自由分配时。我们必须使用该内存块进行分配。
  3. 从初始块中分配时,初始块可用时。

有关详细信息,请参见图表。 Diagram for allocating algo of memory

malloc的源代码

#define TRUE        1
#define FALSE       0

#define MAX_ALOCATION_ALLOWED       20
static unsigned char our_memory[1024 * 1024];

static int g_allocted_number = 0;
static int g_heap_base_address = 0;

typedef struct malloc_info
{
    int address;
    int size;
}malloc_info_t;

malloc_info_t   metadata_info[MAX_ALOCATION_ALLOWED] ={0};

void* my_malloc(int size)
{
    int j =0;
    int index = 0 ;
    int initial_gap =0;
    int gap =0;
    int flag = FALSE;
    int initial_flag = FALSE;
    void *address = NULL;
    int heap_index = 0;
    malloc_info_t temp_info = {0};

    if(g_allocted_number >= MAX_ALOCATION_ALLOWED)
    {
        return NULL;
    }

    for(index = 0; index < g_allocted_number; index++)
    {
        if(metadata_info[index+1].address != 0 )
        {
            initial_gap = metadata_info[0].address - g_heap_base_address; /*Checked Initial Block (Case 3)*/
            if(initial_gap >= size)
            {
                initial_flag = TRUE;
                break;
            }
            else
            {
                gap = metadata_info[index+1].address - (metadata_info[index].address + metadata_info[index].size);  /*Check Gap Between two allocated memory (Case 2)*/
                if(gap >= size)
                {
                    flag = TRUE;
                    break;
                }
            }
        }
    }

    if(flag == TRUE)    /*Get Index for allocating memory for case 2*/
    {
        heap_index = ((metadata_info[index].address + metadata_info[index].size) - g_heap_base_address);
    
        for(j = MAX_ALOCATION_ALLOWED -1; j > index+1; j--)
        {
            memcpy(&metadata_info[j], &metadata_info[j-1], sizeof(malloc_info_t));
        }
    }
    else if (initial_flag == TRUE) /*Get Index for allocating memory for case 3*/
    {
        heap_index = 0;
        for(j = MAX_ALOCATION_ALLOWED -1; j > index+1; j--)
        {
            memcpy(&metadata_info[j], &metadata_info[j-1], sizeof(malloc_info_t));
        }
    }
    else /*Get Index for allocating memory for case 1*/
    {
        if(g_allocted_number != 0)
        {
            heap_index = ((metadata_info[index -1].address + metadata_info[index-1].size) - g_heap_base_address);
        }
        else    /* 0 th Location of Metadata for First time allocation*/
            heap_index = 0;
    }

    address = &our_memory[heap_index];
    metadata_info[index].address = g_heap_base_address + heap_index;
    metadata_info[index].size = size;

    g_allocted_number += 1;
    return address;
}

现在免费提供代码

void my_free(int address)
{
    int i =0;
    int copy_meta_data = FALSE;
    
    for(i = 0; i < g_allocted_number; i++)
    {
        if(address == metadata_info[i].address)
        {
            // memset(&our_memory[metadata_info[i].address], 0, metadata_info[i].size);
            g_allocted_number -= 1;
            copy_meta_data = TRUE;
            printf("g_allocted_number in free = %d %d\n", g_allocted_number, address);
            break;
        }
    }
    
    if(copy_meta_data == TRUE)
    {
        if(i == MAX_ALOCATION_ALLOWED -1)
        {
            metadata_info[i].address = 0;
            metadata_info[i].size = 0;
        }
        else
            memcpy(&metadata_info[i], &metadata_info[i+1], sizeof(malloc_info_t));
    }
}

要立即测试,测试代码为

int main()
{
    int *ptr =NULL;
    int *ptr1 =NULL;
    int *ptr2 =NULL;
    int *ptr3 =NULL;
    int *ptr4 =NULL;
    int *ptr5 =NULL;
    int *ptr6 =NULL;
    
    g_heap_base_address = &our_memory[0];

    ptr = my_malloc(20);
    ptr1 = my_malloc(20);
    ptr2 = my_malloc(20);
    
    my_free(ptr);
    ptr3 = my_malloc(10);
    ptr4 = my_malloc(20);
    ptr5 = my_malloc(20);
    ptr6 = my_malloc(10);
    
    printf("Addresses are: %d, %d, %d, %d, %d, %d, %d\n", ptr, ptr1, ptr2, ptr3, ptr4, ptr5, ptr6);

    return 0;
}