5

これであなたの助けが必要です。私はCの平均的な知識を持っており、ここに問題があります。いくつかのベンチマークを使用して、新しいプロセッサでいくつかのコンピュータアーキテクチャのもの(ブランチミス、キャッシュミス)をテストしようとしています。ベンチマークはCであるということですが、ライブラリ呼び出しを含めてはなりません。たとえば、エラーが発生したため、mallocを使用できません

"undefined reference to malloc" 

ライブラリを含めても。だから私は自分のmallocを書かなければなりません。私はそれが超効率的であることを望んでいません-ただ基本をしてください。メモリにアドレスが必要だと思っているので、mallocが発生するたびに、そのアドレスへのポインタを返し、そのサイズでカウンタをインクリメントします。私のプログラムではMallocが2回発生するため、大容量のメモリも必要ありません。

それについて私を助けてくれませんか?私は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

上記のスレッドセーフなnosの答えを試してみて、私は彼のコードを以下のようにいくつか変更して参照しています。

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またはシステムの同等物に対してリンクする必要があります。標準のClibを使用しない場合、main関数の前に実行されるスタートアップコードも取得されません。あなたのプログラムは決して実行されません...

次のように、静的データのブロックを割り当てて、mallocの代わりに使用することができます。

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

static char [100000] fred;

または、起動時に連続メモリの大きなブロックに対して標準のmallocを呼び出し、それを分割するために独自のmallocタイプの関数を記述します。2番目のケースでは、ベンチマークに影響を与えないように、システムのmallocを呼び出した後にベンチマークを開始します。

于 2012-12-07T14:12:18.153 に答える
2

私はMallocの完全なアプローチを共有しており、すべてのシナリオで無料で機能します。これは、配列を使用して補完されます。メタデータのリンクリストを使用して実装することもできます。

カバーしなければならない3つのシナリオがあります

  1. 継続的なメモリ割り当て:継続的な方法でメモリを割り当てます
  2. 2つの割り当てられたメモリ間で割り当てられたメモリ:メモリが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 に答える