malloc safe in 1.6.5?

hi there, i use arduino 1.6.5 and have a midi controller working here quite well. i copied quite a bit of code from another project and adapted it to my needs. the code i borrowed uses malloc and free in some places. is this safe to use in 1.6.5? i read somewhere that there are bugs in the implementation. i would also gladly replace the malloc calls, but i don't understand the statement coming with it, here is an excerpt:

activeNotes[2] = (Note *) malloc(sizeof(Note));

malloc does allocate sizeof Notes unsigned ints? so in my case 3? or what exactly? the Note class looks like this:

class Note {
 unsigned int _number;
  unsigned int _velocity;
 unsigned int _fretted;
  
  public:
  void init(unsigned int number, unsigned int velocity,unsigned int fretted) {
    _number = number;
    _velocity = velocity;
    _fretted = fretted;
  }
  
 unsigned int number() {
    return _number;
  }
  
 unsigned int velocity() {
    return _velocity;
  }
  
 unsigned int fretted() {
    return _fretted;
  }

  
};

and what does the (Note* ) mean? simply multiplication?

how would go about replacing malloc and free with a fixed size array of variables in this case?

i can happily post more code if needed, thanks for any insight!

I have no idea whether or not malloc is safe on that version but if you think

and what does the (Note* ) mean? simply multiplication?

you must do much more homework on C and pointers before you proceed

so that is a pointer, thank you.

yeah i need to do much more homework to understand that code, however i was able to adopt it perfectly to my needs, even without understanding pointers. will read that up. i would still be glad to hear if malloc is safe or not and get some pointers (sic!) on how to replace it if it is not safe.

lokki: malloc safe in 1.6.5?

The IDE version is irrelevant. It is avr-libc and the avr-gcc compiler that generates the code.

To answer your question, yes malloc() is "safe" (despite what some people here say).

If you doubt it, simply write a sketch that allocates and frees a memory block over and over again in a loop (along with the "freeMemory" code).

Let it run as long as you want... you will see that it works just fine.

Here's a test that I ran on a MEGA2560 (notice ONE MILLION ITERATIONS):

int main (void)
{
    char *buf1;
    char *buf2;
    uint16_t siz1;
    uint16_t siz2;
    size_t mem;
    size_t start;
    uint32_t iterations;

    init();
    Serial.begin (115200);

    start = memoryFree();
    iterations = 1000000UL;

    fprintf (stdout, "Running");

    while (iterations--) {

        if ((iterations % 10000) == 0) {
            fprintf (stdout, ".");
        }

        while (((siz1 = rand()) > 3500));
        while (((siz2 = rand()) > 3500));

        buf1 = (char *) malloc (siz1 * sizeof (char));
        buf2 = (char *) malloc (siz2 * sizeof (char));

        if ((siz1 % 2) == 0) {
            free (buf1); // free malloc in random order
            free (buf2);
        } else {
            free (buf2);
            free (buf1);
        }

        mem = memoryFree();

        if (mem != start) {
            fprintf (stdout, "\nFailure: expected %u, got %u\n", start, mem);
            while (1);
        }
    }

    fprintf (stdout, "\nDone - no errors!\n");
    while (1);
}

And the result was:

[b]Running...
Done - no errors![/b]

(why the editor removed all the progress dots I don't understand...)

'nuf said.

lokki: i read somewhere...

If you don't know about pointers, then you don't know how to use malloc/free safely. krupski's trivial example is indeed safe: allocating and freeing the same memory within the same scope.

If the ONLY thing you ever malloc is a Note, then it is safe. If there are two (or more) different things that you malloc, then it is probably not safe. There are no bugs in malloc/free -- the problem is unsafe usage.

It would be much better (and faster) to have a regular Note array (a "pool" of Notes), and use elements of that array when you need them. Depending on their lifetimes, you could use

  • an index to the next free Note you can use (i.e., a stack)

  • two indices that point to the next free Note and the last used Note (i.e., a FIFO or ring buffer)

  • an index in each Note that lets you link free Notes together (i.e., random access in a singly linked list). You would have a first free index as a starting point for the free Notes.

If you are using String, none of this is safe, because you don't know how to use them safely. String uses malloc/free internally, and so there are different sizes being allocated. That's what leads to memory fragmentation.

Cheers, /dev

-dev: If there are two (or more) different things that you malloc, then it is probably not safe.

"probably not safe"? I use malloc/free/new/delete all the time, on many different "things" and in many different scopes, have done so for, literally, decades, and have never once had a problem. To say that it is "probably not safe" is is pure nonsense....

You might as well say writing c++ code is "probably not safe", unless you can write perfect, bug-free code on the first try every time. Proper use of malloc/free/new/delete is easy enough to verify by monitoring memory usage, tracking, object creation/deletion, etc. If you're fragmenting memory, or leaking memory, those are BUGS! malloc and free are PERFECTLY SAFE if used properly. Perhaps we should also warn people that using arrays is "probably not safe" ,because you might write past the end? Or pointers are "probably not safe" because you might not initialize them properly?

Regards, Ray L.

LOL, I think I did pretty well, if the only thing you disagreed with is “probably”, and even that required reductio ad absurdum. I really worked to make a neutral-tone, factual response.

I can’t argue with your tautology: “malloc and free are PERFECTLY SAFE if used properly.” Truth.

I would argue that there are different categories of bugs:

* those that have obvious, immediate, repeatable manifestations, and

* those that have subtle, latent, random manifestations.

Improper use of malloc/free falls into the latter category, and is the main pitfall for inexperienced users. If they don’t understand pointers, memory use and scoping, there’s no hope that they will recognize and then solve a malloc/free bug. Hence the warning to the OP.

Proper use is obviously not a problem for you, because you have decades of experience. After the OP has more experience, it won’t be a problem for them, either.

Cheers,
/dev

-dev: If they don't understand pointers, memory use and scoping, there's no hope that they will recognize and then solve a malloc/free bug. Hence the warning to the OP.

Then tell them THAT! DON'T make them think malloc is inherently evil and "probably not safe". That is exactly how people get the crazy ideas that things like malloc, String, etc. are inherently dangerous and unstable, and should never, ever be used. They are not, they simply HAVE to learn how to use them properly, which takes study, and time. If someone just learned to drive a car yesterday, I wouldn't tell them driving on a freeway is inherently dangerous, but it is something they need to work up to over time.

Regards, Ray L.

-dev: If you don't know about pointers, then you don't know how to use malloc/free safely. krupski's trivial example is indeed safe: allocating and freeing the same memory within the same scope.

If you look at my code, you see that I malloc random sized buffers (the only thing being that the total size is less than my 8K of sram).

Also, I free them in random order... sometimes the first then the second, sometimes the second then the first.

As far as using and freeing memory "in the same scope", when would this ever NOT be the case?

RayLivingston: "probably not safe"? I use malloc/free/new/delete all the time, on many different "things" and in many different scopes, have done so for, literally, decades, and have never once had a problem. To say that it is "probably not safe" is is pure nonsense....

You might as well say writing c++ code is "probably not safe", unless you can write perfect, bug-free code on the first try every time. Proper use of malloc/free/new/delete is easy enough to verify by monitoring memory usage, tracking, object creation/deletion, etc. If you're fragmenting memory, or leaking memory, those are BUGS! malloc and free are PERFECTLY SAFE if used properly. Perhaps we should also warn people that using arrays is "probably not safe" ,because you might write past the end? Or pointers are "probably not safe" because you might not initialize them properly?

Regards, Ray L.

THANK YOU!!!!!

-dev:
LOL, I think I did pretty well, if the only thing you disagreed with is “probably”, and even that required reductio ad absurdum. I really worked to make a neutral-tone, factual response.

I can’t argue with your tautology: “malloc and free are PERFECTLY SAFE if used properly.” Truth.

I would argue that there are different categories of bugs:

* those that have obvious, immediate, repeatable manifestations, and

* those that have subtle, latent, random manifestations.

Improper use of malloc/free falls into the latter category, and is the main pitfall for inexperienced users.

Improper use of ANYTHING, in ANY programming language can lead to problems, crashes and subtle bugs that SEEM to be random. This can happen when the programmer is inexperienced or makes a simple mistake.

None of this, however, implies that the function(s) the programmer used improperly are “unsafe”.

And, by the way, linking certain words to allow lookup is a bit insulting. Do you think we all have a 100-or-less word vocabulary? ESPECIALLY “Reductio ad absurdum”. That’s a common tactic among Internet users to either insult or to disprove a point. EVERYONE knows that.

Try looking up “Ad nauseaum” (hint: it’s associated with Arduino floating point problems) :slight_smile:

krupski: As far as using and freeing memory "in the same scope", when would this ever NOT be the case?

It is, in fact, VERY often not the case. I have one application that allocates and de-allocates hundreds of buffers per second. They are malloc'd in an interrupt "task", and free'd in the "foreground task" - completely different scopes. This is quite common in 'producer-consumer' and messaging applications. Once a block of memory is allocated, it makes no difference when/where/how it was allocated, and anyone who has a pointer to it can de-allocate it regardless of scope, so the original point about scope was rather specious to begin with. Regards, Ray L.

lokki: is this safe to use in 1.6.5?

https://github.com/arduino/Arduino/issues/857

cmaglie closed this in d457332 on Dec 17, 2012

https://github.com/arduino/Arduino/tree/1.6.5-r5

Latest commit b469b30 on Aug 28, 2015

Appears to have been fixed long before you downloaded 1.6.5.

wow, thank you all. i duck now and read up on pointers.

RayLivingston: they simply HAVE to learn how to use them properly,

We will have to agree to disagree. Many other techniques are demonstrably more efficient, robust and easier to understand for new users, especially when it comes to long term behavior.

krupski: I free them in random order... sometimes the first then the second, sometimes the second then the first.

Um... that's a trivial example. I would even say it's an example of "proper" usage. It's the "improper" usage that is problematic (unsafe).

krupski: That's a common tactic among Internet users...

I'm really not trying to insult anyone. I'm trying to inform and to make sure my meaning is clear. I'm starting to think I should have linked the word "unsafe". :D

RayLivingston: They are malloc'd in an interrupt "task", and free'd in the "foreground task" - completely different scopes. This is quite common in 'producer-consumer' and messaging applications. Once a block of memory is allocated, it makes no difference when/where/how it was allocated, and anyone who has a pointer to it can de-allocate it regardless of scope

malloc/free is not interrupt-safe, if that is your literal meaning. This is an example of improper use (interleaving lifetimes) that can lead to fragmentation.

Well, this is a forum, after all. If "safe" is the only opinion being offered WRT malloc/free, I hope someone takes the time to point out the pitfalls.

RayLivingston: It is, in fact, VERY often not the case. I have one application that allocates and de-allocates hundreds of buffers per second. They are malloc'd in an interrupt "task", and free'd in the "foreground task" - completely different scopes. This is quite common in 'producer-consumer' and messaging applications. Once a block of memory is allocated, it makes no difference when/where/how it was allocated, and anyone who has a pointer to it can de-allocate it regardless of scope, so the original point about scope was rather specious to begin with. Regards, Ray L.

Yup.. thinking about it, I free allocated memory via a pointer from different functions all the time. Somehow in my head "scope" was meaning "same program" when it actually means "same function". My bad. You're right.

-dev: Um... that's a trivial example. I would even say it's an example of "proper" usage. It's the "improper" usage that is problematic (unsafe).

Again, what's the point? If someone uses a function "improperly" and then runs into problems, that does not make the FUNCTION "problematic".

As far as suggesting that "pitfalls" of malloc/free be pointed out, what about "uint8_t"? I say "uint8_t x = 1234;" and now "x" is 210? What the heck? Are 8 bit unsigned ints "problematic"? Should we discuss the "pitfalls" of 8 bit unsigned ints?

This is ridiculous.

-dev: malloc/free is not interrupt-safe, if that is your literal meaning. This is an example of improper use (interleaving lifetimes) that can lead to fragmentation.

It may, or may not, be inherently interrupt-safe, but it absolutely can be used in an interrupt-safe manner regardless, which is exactly what I do. Never had a problem.

Regards, Ray L.

It may, or may not, be inherently interrupt-safe.

There is no "may" about it. It is not interrupt-safe, for a variety of reasons. My favorite reason is that you shouldn't do a non-deterministic search during an ISR.