Hard fault in __free_r

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Hard fault in __free_r

Trampas Stern
So I was trying to be cleaver, which I should not do....

I have an embedded design where I was creating driver classes.  For low
power I wanted the drivers to get turned off when not in use.  Therefore I
was looking at using smart pointers, and having destructor turn off the
driver.

Note smart pointers as implemented call new and malloc memory on the heap,
but I could write a new template/class that would not.  However I ran into
another problem.

I create some memory for my driver, say UART like so:

uint8_t UartStorage[sizeof(UART)]  __attribute__ ((aligned (8)));

Then I allocate my UART like:

Uart *ptrUart=new(UartStorage) UART(....);

However I have found that sometimes when I call delete on the pointer the
processor will get a hard fault in __free_r.  I could not find the source
for __free_r to see if the static allocation in new was causing a problem
or not, but thought I would post and see if others have seen this?
Also this hard fault was not consistent. That is after allocating and
deleting object a random amount of times from the same static storage
address it would fail.

I took this as a sign I was pushing the bleeding edge a bit too much and
went back to good old static allocation (no new) and just doing an
acquire() and release().

Thanks,
Trampas
Reply | Threaded
Open this post in threaded view
|

Re: Hard fault in __free_r

Freddie Chopin
Hello Trampas!

Your mistake here is that when using placement-new you MUST NOT call
delete. The memory is not from the heap, therefore trying to return it
to the heap (via calling delete, which in turn calls free) is just
completely wrong and forbidden by the language.

Your object must be explicitly destructed manually or via special
delete-function supplied to the smart pointer (I assume you talk about
things like std::unique_ptr<>). Therefore you either need to do:

ptrUart->~Uart();

when you are done, or - if you use smart pointers, create a no-op
function and supply that to the smart pointer during construction.

I have done something like that in my C++11 RTOS for ARM
microcontrollers. Here is the "no-op deleter" which I mentioned:

https://github.com/DISTORTEC/distortos/blob/master/include/distortos/in
ternal/memory/dummyDeleter.hpp

You may create a type alias for your smart pointer to make things
easier:

https://github.com/DISTORTEC/distortos/blob/master/include/distortos/in
ternal/scheduler/Stack.hpp#L37

And then you just assign both the pointer _and_ the deleter to the
smart pointer object, for example see the highlighted line:

https://github.com/DISTORTEC/distortos/blob/master/include/distortos/St
aticThread.hpp#L58

With this design the smart pointer can use any kind of memory - the
only difference is in the deleter you have to supply which will be
executed at the end. If you want to also use devices which are really
dynamically allocated (from the heap, with normal `new` or array-
`new`), then just use a different function, like this one:

https://github.com/DISTORTEC/distortos/blob/master/include/distortos/in
ternal/memory/storageDeleter.hpp

Usage example:

https://github.com/DISTORTEC/distortos/blob/master/include/distortos/in
ternal/scheduler/DynamicThreadBase.hpp#L214

BTW - if you use C++ and happen to work with an ARM Cortex-M
microcontroller, you may find my project quite interesting, at least I
hope so (;

Regards,
FCh
Reply | Threaded
Open this post in threaded view
|

Re: Hard fault in __free_r

Freddie Chopin
In reply to this post by Trampas Stern
I'm resending the message again, this time with proper (not wrapped)
links (; sorry for that...

----------------------------------------------------------------------

Hello Trampas!

Your mistake here is that when using placement-new you MUST NOT call
delete. The memory is not from the heap, therefore trying to return it
to the heap (via calling delete, which in turn calls free) is just
completely wrong and forbidden by the language.

Your object must be explicitly destructed manually or via special
delete-function supplied to the smart pointer (I assume you talk about
things like std::unique_ptr<>). Therefore you either need to do:

ptrUart->~Uart();

when you are done, or - if you use smart pointers, create a no-op
function and supply that to the smart pointer during construction.

I have done something like that in my C++11 RTOS for ARM
microcontrollers. Here is the "no-op deleter" which I mentioned:

https://github.com/DISTORTEC/distortos/blob/master/include/distortos/internal/memory/dummyDeleter.hpp

You may create a type alias for your smart pointer to make things
easier:

https://github.com/DISTORTEC/distortos/blob/master/include/distortos/internal/scheduler/Stack.hpp#L37

And then you just assign both the pointer _and_ the deleter to the
smart pointer object, for example see the highlighted line:

https://github.com/DISTORTEC/distortos/blob/master/include/distortos/StaticThread.hpp#L58

With this design the smart pointer can use any kind of memory - the
only difference is in the deleter you have to supply which will be
executed at the end. If you want to also use devices which are really
dynamically allocated (from the heap, with normal `new` or array-
`new`), then just use a different function, like this one:

https://github.com/DISTORTEC/distortos/blob/master/include/distortos/internal/memory/storageDeleter.hpp

Usage example:

https://github.com/DISTORTEC/distortos/blob/master/include/distortos/internal/scheduler/DynamicThreadBase.hpp#L214

BTW - if you use C++ and happen to work with an ARM Cortex-M
microcontroller, you may find my project quite interesting, at least I
hope so (;

Regards,
FCh

Reply | Threaded
Open this post in threaded view
|

Re: Hard fault in __free_r

Trampas Stern
Freddie,

Thanks for the information!

What I was trying to do using the smart pointers was to make a way to start
and stop peripherals for low power.   The basic idea is something along the
ideas of:

size_t print(char *str)
{
Uart *ptrUart = Board->getUart0();  // gets pointer to Uart0, if no one is
using Uart0 it powers on and initializes it.
// Use uart as needed .

} //at end of function the uart is released, in the board board class it
will power off uart0 if no other code is using it.


I found two problems:

1. was that smart pointers allocate memory from stack, which I did not want.
2. the __free_r problem.

I went back to doing the "C way" where I call an acquire() and release()
function.

Again I am an old school embedded guy, but like some of the C++ features.
One of the things I dislike about C++ is also its advantage, that is it
does things like the delete behind the scenes.  I have almost decided it is
better to use the acquire() and release() such that next guy reading code
(me in 6 months) knows what it is doing and then use the C++ delete feature
to be an error check that you called release().

I was getting ready to do a project using an RTOS (was thinking freeRTOS)
but I will look at your project.

Trampas

On Sat, Dec 2, 2017 at 9:32 AM, Freddie Chopin <[hidden email]> wrote:

> I'm resending the message again, this time with proper (not wrapped)
> links (; sorry for that...
>
> ----------------------------------------------------------------------
>
> Hello Trampas!
>
> Your mistake here is that when using placement-new you MUST NOT call
> delete. The memory is not from the heap, therefore trying to return it
> to the heap (via calling delete, which in turn calls free) is just
> completely wrong and forbidden by the language.
>
> Your object must be explicitly destructed manually or via special
> delete-function supplied to the smart pointer (I assume you talk about
> things like std::unique_ptr<>). Therefore you either need to do:
>
> ptrUart->~Uart();
>
> when you are done, or - if you use smart pointers, create a no-op
> function and supply that to the smart pointer during construction.
>
> I have done something like that in my C++11 RTOS for ARM
> microcontrollers. Here is the "no-op deleter" which I mentioned:
>
> https://github.com/DISTORTEC/distortos/blob/master/include/
> distortos/internal/memory/dummyDeleter.hpp
>
> You may create a type alias for your smart pointer to make things
> easier:
>
> https://github.com/DISTORTEC/distortos/blob/master/include/
> distortos/internal/scheduler/Stack.hpp#L37
>
> And then you just assign both the pointer _and_ the deleter to the
> smart pointer object, for example see the highlighted line:
>
> https://github.com/DISTORTEC/distortos/blob/master/include/
> distortos/StaticThread.hpp#L58
>
> With this design the smart pointer can use any kind of memory - the
> only difference is in the deleter you have to supply which will be
> executed at the end. If you want to also use devices which are really
> dynamically allocated (from the heap, with normal `new` or array-
> `new`), then just use a different function, like this one:
>
> https://github.com/DISTORTEC/distortos/blob/master/include/
> distortos/internal/memory/storageDeleter.hpp
>
> Usage example:
>
> https://github.com/DISTORTEC/distortos/blob/master/include/
> distortos/internal/scheduler/DynamicThreadBase.hpp#L214
>
> BTW - if you use C++ and happen to work with an ARM Cortex-M
> microcontroller, you may find my project quite interesting, at least I
> hope so (;
>
> Regards,
> FCh
>
>