This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Malloc returns NULL

Setup

Keil: uVision 5.17.0.0
ARM: LPC1768
A standard project with some UARTS and I2C
"Use memory Layout form target" is checked (using the standard scatter file)
"Use MicroLIB" is not checked

from startup_LPC17xx.s
Heap_Size EQU 0x00002000

AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit

Problem
Any call to malloc returns NULL, that is, the system can not allocate memory.

Why does not the mallco work, is my only options to
1) Use microLIB
2) Implement _init_alloc() and __rt_heap_extend() on my own

?

Regards Stefan

  • Additional information

    I have even tried an own scatter file

    RW_IRAM_STACK 0x10000000 0x10002000 { ; RW data .ANY (STACK) }

    RW_IRAM1 0x10002000 0x10006000 { ; RW data .ANY (+RW +ZI) }

    RW_IRAM_HEAP 0x10006000 0x10008000 { ; RW data .ANY (HEAP) }

    But this does not work either

    It also seems that the code does not call the default generated code

    IMPORT __use_two_region_memory EXPORT __user_initial_stackheap
    __user_initial_stackheap

  • Additional information

    It seems that it thinks i am on a "bare metal" despite i have a

    int main(int argc, char **argv)

    becouse if i make the call
    _init_alloc((uintptr_t)&__heap_base, (uintptr_t)&__heap_limit);

    in the begining of my main the malloc stuff works later works however i can not realy do this becosue the main argument (argc and argv ) would require a heap allocation

    Regards Stefan

  • I didn't new argc and argv would need any heap allocation - why would they?

    Next thing - I have never used argc and argv on a bare-bones embedded platform, since I wouldn't have any operating system sending in any parameters from any command-line.

    What magic do you send in through these parameters?

  • That really seems like the way you would allocate a heap in previous versions, but not in any recent.

    See if this helps.

    www.keil.com/.../ARMLINK_pge1362065977713.htm

    i.e make an ARM_LIB_HEAP region and it will be initialized for use before main is called.

  • Third field in scatter file region description is the length of the region, not the end address.

      RW_IRAM1 0x20000000 0x00040000  {  ; RW data 256KB
       .ANY (+RW +ZI)
      }
    

  • Or if you want to go the path you are, you can implement the __user_initial_stackheap function yourself.

    ; User Initial Stack & Heap
    
                    IF      :DEF:__MICROLIB
    
                    EXPORT  __initial_sp
                    EXPORT  __heap_base
                    EXPORT  __heap_limit
    
                    ELSE
    
                    IMPORT  __use_two_region_memory
                    EXPORT  __user_initial_stackheap
    __user_initial_stackheap
    
                    LDR     R0, =  Heap_Mem
                    LDR     R1, =(Stack_Mem + Stack_Size)
                    LDR     R2, = (Heap_Mem +  Heap_Size)
                    LDR     R3, = Stack_Mem
                    BX      LR
    
    

  • To Per Westermark

    Accoring the searching I did before I made post it said that a main like this, "int main(int argc, char **argv)" require a initiation of the heap. That is, the function __user_initial_stackheap must/will be called unlike if "use microlib" is checked, then the main must look like this "void main(void)"


    To Westonsupermare Pier

    I have changed it, but it wont call the __user_initial_stackheap before calling main


    To Robert McNamara

    ARM_LIB_HEAP: Yes, i have tested it, it did not make any difference, it still wont call __user_initial_stackheap before main(...)

    __user_initial_stackheap is included, I used "new project" option the keil and it automatically produced that code, but it is not calle



    To All
    Becosue "new project" produced startup_LPC17xx.s, with the stack, heap reserved and __user_initial_stackheap created (without changing the scatter file) I assumed everything should be working, but it seems not to be.



    Regards Stefan

  • No, it is pure C, one single main function

    I even recreated an empty project ("use microlib" unchecked) to test it again.
    When i step into the malloc function i can see that the malloc function consider the heap to be full and it wont call the __user_initial_stackheap

    In the map file the following exists so something is going on

    __user_initial_stackheap 0x000002cd Thumb Code 0 startup_lpc17xx.o(.text)
    __use_two_region_memory 0x000002f1 Thumb Code 2 heapauxi.o(.text)
    __rt_heap_escrow 0x000002f3 Thumb Code 2 heapauxi.o(.text)
    __rt_heap_expand 0x000002f5 Thumb Code 2 heapauxi.o(.text)
    __use_no_heap 0x000002f7 Thumb Code 2 hguard.o(.text)


    Is it possibly to get the source code to the c libraries that the linker automatically links in so i can compare it to the executed assembler instructions in "malloc" ?

    and that coudl help me to understand why it is not calling the __user_initial_stackheap


    Regards

  • What size is your heap?

    How much are you trying to allocate in your main?

    If you make the heap 0 in size, does it crash before main?

    If you make the heap larger does it eventually work?

    When you set your breakpoint in __user_initial_stackheap, make sure you also right click and then left click "show disassembly at ###" Then see if it stops in your __user_inital_stackheap.


  • startup_LPC17xx.s

    Stack_Size      EQU     0x00000800
    
                    AREA    STACK, NOINIT, READWRITE, ALIGN=3
    Stack_Mem       SPACE   Stack_Size
    __initial_sp
    
    
    ; <h> Heap Configuration
    ;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
    ; </h>
    
    Heap_Size       EQU     0x00000800
    
                    AREA    HEAP, NOINIT, READWRITE, ALIGN=3
    __heap_base
    Heap_Mem        SPACE   Heap_Size
    __heap_limit
    

    Scatter file

    
    LR_IROM1 0x00000000 0x00080000  {    ; load region size_region
      ER_IROM1 0x00000000 0x00080000  {  ; load address = execution address
        *.o (RESET, +First)
        *(InRoot$$Sections)
        .ANY (+RO)
      }
    
      RW_IRAM_STACK 0x10000000 0x2000  {  ; RW data
        .ANY (STACK)
      }
    
      LO_ARM_TEST 0x10002000 UNINIT 0x20 {  ; RW data
        .ANY (__LO_ARM_TEST_RAM_AREA)
      }
    
      RW_IRAM1 0x10002020 0x3FE0  {  ; RW data
        .ANY (+RW +ZI)
      }
    
      RW_IRAM_HEAP 0x10006000 0x2000 {  ; RW data
        .ANY (HEAP)
      }
    }
    

    yes, i have the assembler view up as awell, i have a break point at __user_inital_stackheap and the main function


    The execution do

    
                    LDR     R0, =SystemInit
                    BLX     R0
                    LDR     R0, =__main
                    BX      R0
    

    And then it will hit the main function without hitting __user_inital_stackheap.

    If i do
    v = malloc(0x10);

    it will return NULL
    but if i have called _init_alloc((uintptr_t)&__heap_base, (uintptr_t)&__heap_limit); before the malloc it will not return a NULL pointer and the pointer is in "right area"

    "use microlib" is unchecked, my main function look like this

    int main(int argc, char **argv)
    


    I have not tested to set "If you make the heap 0 in size, does it crash before main?"



    Regards Stefan

  • heap test of 0?

    Try removing __user_initialize_stackheap and the EXPORT of it from the startup file. Do you get a link error?

  • Test1

    Heap_Size       EQU     0x00000000
    
    Result:
    No compilation error
    It hangs inside _init_alloc call in the main function
    



    Test2

    Heap_Size       EQU     0x00000000
    ;                EXPORT  __user_initial_stackheap
    //  _init_alloc((uintptr_t)&__heap_base, (uintptr_t)&__heap_limit);
    Result:
    No compilation error
    It never reach the main() function
    



    Test3:

    Heap_Size       EQU     0x00000800
    ;                EXPORT  __user_initial_stackheap
    //  _init_alloc((uintptr_t)&__heap_base, (uintptr_t)&__heap_limit);
    Result:
    No compilation error
    It reach the main() function
    and malloc returns a valid pointer (that is, it points into the right area)
    

    wtf, why would it work corretly with "standard" code comment out?

    Regards

  • "That really seems like the way you would allocate a heap in previous versions, but not in any recent."

    So maybe you got two separate functions that tries to initialize the heap.