Skip to content

The implementation of __real__malloc_r #7250

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
leibin2014 opened this issue Jun 19, 2018 · 11 comments
Closed

The implementation of __real__malloc_r #7250

leibin2014 opened this issue Jun 19, 2018 · 11 comments

Comments

@leibin2014
Copy link
Contributor

Description

Dear experts,
When I run the example project Nucleo_rtos_basic on stm32f103 I get an error. The function thread.start(print_thread) goes to call the function malloc, then malloc will call malloc_wrapper() because of linker flag -Wl,--wrap,_malloc_r. Finally __real__malloc_r() will be called. But there is no definition of __real__malloc_r() . So malloc will return NULL and assert the mbed error. My question is where is the implementation of __real__malloc_r? It doesn't look like a standard lib function.

Issue request type

[X] Question
[ ] Enhancement
[ ] Bug

@ciarmcom
Copy link
Member

ARM Internal Ref: MBOTRIAGE-777

@0xc0170
Copy link
Contributor

0xc0170 commented Jun 19, 2018

There should be definition of the real malloc otherwise would not link. __real__malloc_r should be the "real" malloc that is defined in the library.

Look at --wrap option (_real symbol is the real name)

@leibin2014
Copy link
Contributor Author

leibin2014 commented Jun 19, 2018

@0xc0170
I just rechecked that hread.start(print_thread) goes to call operator new[]() and then call the function malloc() in mbed_retarget.cpp line 1481. Finally malloc() returns NULL. The malloc_wrapper() is not called as I thought. So the problem is that why malloc() returns NULL? I tested this with the default VSCODE-GCC-ARM type project Nucleo_rtos_basic exported from the online compiler.

@0xc0170
Copy link
Contributor

0xc0170 commented Jun 19, 2018

@leibin2014
Copy link
Contributor Author

leibin2014 commented Jun 20, 2018

@0xc0170
The value of heap_stats is: current_size: 0, max_size: 0, total_size: 0, reserved_size:5696, alloc_cnt: 0, alloc_fail_cnt: 1.
The error happens when malloc(3096) is called. But no error happens when malloc(2576) is called. Looks like the max size can be allocated is some value between 2500 ~ 3000.
I also tried calling malloc(2048) twice, the first calling can return a right pointer, but the second one returns NULL. If I add free(address0) after the first calling of malloc(2048), then the second calling can return right pointer.

@leibin2014
Copy link
Contributor Author

leibin2014 commented Jun 21, 2018

So where the max heap size is set? Should be some code similar as below in startup_stm32XB.S to set the heap size? But I can't find it in the startup file. Or there should be somewhere tell the libc about heap size. As expect it should be in the pre_main() function. But for GCC I can't find it in pre_main(). I'm using the GCC(GNU) toolchain.

    .align 3
#ifdef __HEAP_SIZE
    .equ    Heap_Size, __HEAP_SIZE
#else
    .equ    Heap_Size, 0x80
#endif
    .globl    __HeapBase
    .globl    __HeapLimit
__HeapBase:
    .space    Heap_Size
    .size __HeapBase, . - __HeapBase
__HeapLimit:
    .size __HeapLimit, . - __HeapLimit```

@0xc0170
Copy link
Contributor

0xc0170 commented Jun 21, 2018

See https://os.mbed.com/docs/latest/reference/memory.html

Heap size is dynamic, limit is how much RAM is left (not yet true for IAR, as you are working with GCC - it is there).

You can also review _sbrk implementation we have in mbed_retarget file. It might answer the question about heap limit

@leibin2014
Copy link
Contributor Author

leibin2014 commented Jun 21, 2018

@0xc0170
According you suggestion, I did more debugging. I call malloc(2048) four times. But the first calling malloc(2048) will call __real__malloc_r() and then call _sbrk(2048) twice. This is why this calling consume almost the 5696 bytes of heap size. But other three callings of malloc(2048) just call _sbrk(2048) once. Is it reasonable that the first calling of malloc() call _sbrk() twice? Looks like there is a problem.

@leibin2014
Copy link
Contributor Author

leibin2014 commented Jun 22, 2018

@0xc0170
I have got more clear picture about this problem.

Firstly, the malloc() and _sbrk() are not one to one. For example, when we call malloc(2) firstly, then _sbrk(32) and _sbrk(2656) will be called. The next calling of malloc(xxx) depends on the size xxx wanted to allocate. If the size xxx is much less than 2656, then _sbrk() won't be called after the calling of malloc(xxx). If the size is bigger than 2656, then the second malloc() will call _sbrk(4096) to get more memory. This should be the behavior of malloc, don't know why, but looks like also reasonable.

Then let's analysis why we get that error when we call malloc(4096) on stm32F103RB. As we know the stm32f103RB just has 20K of small RAM. As we see in heap_stats above the heap size is 5760. When we call malloc(4096), then _sbrk(4120) and _sbrk(2664) will be called. Since 4120+2664 is bigger than 5760 the malloc() executes failed and returns NULL.

So the Nucleo_rtos_basic example in online compiler is not working for stm32f103rb. In this example, thread.start(print_thread); will call _attr.stack_mem = new uint32_t[_attr.stack_size/sizeof(uint32_t)];. Since the default value of MBED_CONF_APP_THREAD_STACK_SIZE is 4096, malloc(4096) will finally be called and return NULL then go into mbed error assert.

@0xc0170
Copy link
Contributor

0xc0170 commented Jun 22, 2018

+1 for the analasis. What you are seeing is paging that sbrk does. See this issue #5386. This was reported earlier, and so far no solution.

I would assume this is a duplicate, and we close it favor of 5386 where we link this report as well.

@leibin2014
Copy link
Contributor Author

@0xc0170 OK, let me close it. Thanks for all above support!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants