-
Notifications
You must be signed in to change notification settings - Fork 143
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
Move heap implementation to :platform:heap and make optional #364
Conversation
Nice! 👍
As far a I know you could explicitly delete the
Definitively not. |
GCC disagrees 🤨
|
But I can mark the prototypes as deprected! And at least that way you get a good error message: [[deprecated("Heap is not implemented!")]]
void* operator new(std::size_t size);
// all others new() types too Results in
|
Interesting, learned something new today. However, it's actually worse than deprecation, I cannot add a message why it was poisened, the pragma doesn't allow adding a comment. So you get only this without context: main.cpp:31:18: error: attempt to use poisoned "new"
31 | uint32_t *ptr = new uint32_t[100];
| ^
main.cpp:32:15: error: attempt to use poisoned "malloc"
32 | void *cptr = malloc(100);
| ^ You can however still combine it with the deprecation notice, so that it doesn't compile (what we want) and shows why (also what we want). There's just one problem, the pragma poisons every call to malloc and new including calls that are never used. This is an issue with header files, say I want to use #pragma GCC poison malloc new // included unknowingly via <modm/platform.hpp> for example
#include <memory> Results in this shitshow:
This doesn't happen with the deprecation notice, it only warns about used calls (or, rather non-optimized out calls). However, even if you could use this int res = at_quick_exit([](){/*tumbleweed*/}); Results in:
However, since I had some trouble finding a libc function that actually uses malloc (and arguably this one isn't applicable for embedded systems) I assume this case is fairly rare, and the stdlibc++ too is mostly in headers and little in pure source code, so most of it won't be linked in either. What I would do now is:
cc @chris-durand You're more knowledgeable of the stdlibc++, any better ideas? |
Actually it does happen, it's just that for system headers, the warnings are ignored.
So this is a false positive… Maybe we can inject error messages into the linker? 😓 Furthermore, code that doesn't include the deprecation or |
🤔🤔🤔🤔🤔🤔 What if… modm_section(".Heap_is_not_implemented__Please_include_the__platform_heap__module_in_your_project")
void* operator new(std::size_t) { return (void*)-1; } And in the linkerscript:
Results in:
It… works? I should not be allowed near C++… |
7b29a04
to
1f9b3de
Compare
|
||
// ---------------------------------------------------------------------------- | ||
modm_section("{{ no_heap_section }}") modm_weak | ||
void* _sbrk_r(struct _reent *r, ptrdiff_t size) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually perfect, since _sbrk_r
is not implemented in newlib at all, so I can just implement it here as a weak
function with just the section attribute and no other linker flags (particularly no function wrapping).
This means the user can supply their own malloc implementation if they do not include the :platform:heap
module, by either just simply overwriting _sbrk_r
to use the default newlib allocator or by additionally wrapping the _malloc_r
etc function via the project collectors settings.
430fa3b
to
4e64b7a
Compare
I don't have any better ideas. |
63cef92
to
a12bf3f
Compare
while(1) ; | ||
} | ||
return (void*) heap; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now all that's needed to define your own heap region.
* null pointer, at which time it throws std::bad_alloc. | ||
*/ | ||
if (std::get_new_handler()) std::get_new_handler()(); | ||
else break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chris-durand is this correctly implemented?
I'm done now, and tested this on a bunch of hardware. |
Absent of dissenting reviews, I'll be merging this this afternoon. |
This moves the heap implementation from the
:platform:core
modules to it's own:platform:heap
modules, which allows to build apps without dynamic memory at all (which is the vast majority of modm's examples). The Block allocator is moved to:driver:block.allocator
where it belongs much better.Unfortunately when not including the module and then calling malloc() or new, there aren't any compiler errors, only linker errors, often cryptic (relating to missing sbrk). Not sure if this is a great usibility improvement. But not including this code by default make a difference for tiny targets.
The goal is to add better memory allocators in future, since TLSF has a huge static overhead (several kBs) and newlib's allocator can't deal with mutiple memory regions and is pretty heavy handed too. The Block allocator should be retired.
Fixes #357, fixes #368.
TODO:
:platform:heap