5

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

"undefined reference to malloc" 

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

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

我已经看过以前的答案,但对我来说似乎都太复杂了。此外,我无法访问 KR 书。

干杯!

编辑:也许这可以帮助你更多:我没有使用 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

4 回答 4

22

这是一种非常简单的方法,它可能会让您通过 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 倍数或任何您需要的地址上的内存地址。

于 2012-12-07T14:18:03.507 回答
6

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

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.
} 
于 2014-04-16T21:21:17.070 回答
4

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

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

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

static char [100000] fred;

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

于 2012-12-07T14:12:18.153 回答
2

我正在分享 Malloc 的完整方法,并免费提供它适用于各种场景。使用数组对此进行了补充。我们还可以实现使用元数据的链接列表。

我们必须涵盖三个场景

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

有关详细信息,您可以在图表中看到。内存分配算法图

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;
}
于 2020-09-04T17:58:02.387 回答