2012-04-09 131 views
2

我在我的固件中添加了malloc支持,我想我错过了一些东西!在arm7中使用gcc实现malloc问题:malloc返回NULL

我使用代码的Sourcery克++精简版库的ARM7TDMI处理器和我的代码是基于在此链路中发现的例如:http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/473/t/44452.aspx#539503

我加入我的版本_sbrk的:

char * _sbrk(int incr) 
{ 
    //extern char _end; /* Defined by the linker */ 
    static char *heap_end; 
    char *prev_heap_end; 
    register char* stackPtr; 

    if (heap_end == 0) 
    { 
     // first allocation 
     heap_end =HEAP_END; 
    } 

    prev_heap_end = heap_end; 

    // get current stack pointer 
    asm ("mov %0, sp\n\t" : "=r" (stackPtr)); 



    if (heap_end + incr > stackPtr) { 
     return NULL;// error - no more memory 
     //write (1, "Heap and stack collision\n", 25); 
     //abort(); 
    } 
    heap_end += incr; 
    return (char*) prev_heap_end; 
} 

一些定义了用于通过SBRK:

#define SDRAM_SIZE 16*1024*1024   
#define HEAP_BASE _ebss 
#define HEAP_END ((_stext + SDRAM_SIZE) -1) 
#define HEAP_SIZE HEAP_END - HEAP_BASE 

(_ebss和_stext来自我的连接文件)

这里是我的主,我做了一个简单的malloc /免费电话:

void C_main (void) 
{ 
    char * testmalloc=0; 
    /* Initialize "Heap Descriptor" pointer */ 
    pHeapDescriptor = __rt_embeddedalloc_init ((void*)HEAP_BASE,HEAP_SIZE); 
    testmalloc = malloc(2048); 
    free(testmalloc); 
} 

我运行这个程序步骤模式。当我调用malloc时,它最终会调用我的_sbrk实现,返回值(prev_heap_end)具有期望值,但是当程序返回到main时,testmalloc值为NULL(gcc库中的某处,prev_heap_end丢失)。

有人知道我做错了什么吗?

不知道这是否会帮助,但这是我的gcc编译参数:

arm-none-eabi-gcc -march=armv4t -mcpu=arm7tdmi -dp -c 
-Wa,-adhlns="../../Base/Lib/Pa/main.o.lst" -fmessage-length=0 
-fno-zero-initialized-in-bss -MMD -MP -MF"../../Base/Lib/Pa/main.d" 
-MT"../../Base/Lib/Pa/main.d" -fpic -mlittle-endian -Wall -g3 -gdwarf-2 
../../Base/Hardintrf/Mezzanine/main.c -o"../../Base/Lib/Pa/main.o" 

在此先感谢您的帮助!

+0

您的第一个全局变量没有初始化,所以它们可能不会像最初假设的那样保证为NULL。你尝试过吗? – 2012-04-09 22:12:25

+1

@SB可能有一点,虽然静态变量应该进入BSS,它将被初始化为零,但是值得检查。另一个问题是我认为你应该将heap_end初始化为HEAP_BASE而不是HEAP_END,否则它会在内存之外启动堆,不是吗? – ams 2012-04-10 10:43:13

+0

heap_end在BSS中。你对heap_end是正确的,它必须是HEAP_BASE,现在它工作的很棒!你可以在答案中重复这个,所以我可以标记它! 谢谢! – 2012-04-10 14:40:02

回答

1
if (heap_end == 0) 
{ 
    // first allocation 
    heap_end = HEAP_END; 
} 

这应该阅读:

if (heap_end == 0) 
{ 
    // first allocation 
    heap_end = HEAP_BASE; 
} 

所以你不要在你的堆月底开始你的堆...你可能要考虑一个更好的名字为变量,然后heap_end到首先避免这种混淆。

此外,您不需要使用寄存器修饰符使内联汇编正常工作。编译器足够聪明,可以为你做到这一点。