【问题标题】:making your own malloc function in C在 C 中制作自己的 malloc 函数
【发布时间】:2012-12-07 14:09:11
【问题描述】:

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

"undefined reference to malloc" 

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

你能帮我解决这个问题吗?我设计了一个 Verilog,在 C 方面没有太多经验。

我已经看过以前的答案,但对我来说似乎都太复杂了。另外,我没有 K-R 书。

干杯!

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

编辑2: 我正在测试 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 函数。

【问题讨论】:

  • Code for malloc and free的可能重复
  • 如果您真的想实现自己的 malloc,请查看系统调用 sbrk()brk(),这将帮助您修改堆的大小。
  • @Mike:您一直在询问有关编译的问题,但是对 malloc 的未定义引用似乎是一个链接错误。这在嵌入式编程中很常见。此外,提问者正在对低级计算机体系结构特性进行基准测试,而不是编写用户级应用程序,而且他们似乎在可能无法使用 malloc 的嵌入式环境中工作,正如他们所说。所以你关于编译的问题可能不正确。如果你想追求这个,你应该首先确定 malloc 在库(而不是头文件)中是否真的可用。
  • @ghostrider 这仍然不是相关部分。您正在显示编译命令,但我们需要查看链接器命令。
  • @Let_Me_Be:反对澄清需求与工程是对立的。没有理由不确保正确定义问题。 OP 声明:“我不能包含任何库调用”和“我想知道我是否可以在没有任何系统调用的情况下编写它。”他们已经明确表达了他们的愿望。如果你想回答一个不同的问题,那么你至少应该确认一下情况。

标签: c malloc


【解决方案1】:

这是一种非常简单的方法,可能会让您通过 2 个 malloc:

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 因为由于对齐问题,这将不起作用。 Malloc 必须考虑对齐要求,这就是为什么标准 malloc 总是返回与最严格的对齐要求对齐的内存。您的内存缓冲区和实现都不会这样做。
  • 我想你的意思是if (sizeof our_memory - next_index &lt; sz)。 (如果我们要分配的内存量少于,则返回NULL。)
  • @Let_Me_Be This is a very simple approach...
  • 如果他只需要两块内存,这就结束了……只需静态声明内存块。
  • @ghostrider 根据编译器的文档,malloc 应该可以正常工作。您可能有一些安装/配置问题。而且平台是对齐敏感的,所以这段代码肯定行不通。
【解决方案2】:

尝试上面给出的线程安全无答案,我指的是他的代码,并进行了一些更改,如下所示:

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.
} 

【讨论】:

    【解决方案3】:

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

    您可以分配一个静态数据块并使用它来代替 malloc,例如:

    // char* fred = malloc(10000);
    // equals
    
    static char [100000] fred;
    

    或在启动时为一大块连续内存调用标准 malloc,然后编写你自己的 malloc 类型函数来划分它。在第二种情况下,您将在调用系统的 malloc 后开始基准测试,以免影响基准测试。

    【讨论】:

    • 因为您的原始答案与问题完全无关。
    • 我对“我不能使用 malloc,因为我收到错误 'undefined reference to malloc'”的原始回答是链接到 lib.c,不确定这是无关紧要的,或者你会得到任何地方这样做....
    【解决方案4】:

    我正在分享 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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-30
      相关资源
      最近更新 更多