Am I understanding malloc() correctly?

Hello all,

Background to the question:
I have code that I'm trying to modify and there is a section where servos are initialized. The code is to control an arduino through LabView over serial communications. This is done by uploading a sketch to the arduino and then initializing stuff in LabView. My question is with the Servo initializing specifically,

servos = (VarSpeedServo*) malloc(2*sizeof(VarSpeedServo));
  for(int i=0; i<2; i++)
  {
    servos[i] = VarSpeedServo(); 
  }

I have been searching around a lot to figure out what malloc() does. The first site that helped was Why Use Pointers?: Dynamic Memory Allocation | SparkNotes. Here, I understood malloc() is for dynamic memory allocation and it adds things onto the heap. The reason for the heap is that when a program is running, it can create room for variables that are create at Run-time instead of Compile-time.

I also searched the forums and found Memory Usage - Programming Questions - Arduino Forum. Specifically this section.

  1. Instantiated global or static
  2. Uninstantiated global or static (aka BSS)
  3. Dynamically allocated
  4. Function local variables

When you create one of the first two kinds of variables it is placed at the bottom of the memory space - instantiated first, uninstantiated ones second. Above that goes the heap, which contains any dynamically allocated variables (memory allocated by malloc() or new()). Then there is the "free" space. Finally, at the top of memory, is the stack. In the stack goes (amongst other things) the function local variables.

Global / static variables are created at compile time and can be reported by the IDE as an amount of RAM used. The other kinds are created on the fly by the program - the IDE has no clue what they are or how big they are, or how many of them.

Question:
Is the reason that the servos are in malloc() is because the sketch is uploaded to the arduino with the servos undeclared (Compile-time) and then LabView declares them while the arduino is running?

If that's the case, I am writing code in LabView which needs two servos. I can just declare them as normal without having to do the malloc() stuff because I know the servos have to be there and I don't have to worry about them being created on the fly.

Thank you in advance,
Matt

It seems to me you got it right

There is no reason for malloc(), just create a static sized buffer:

// Use a global
varSpeedServo *servo[2];

malloc() is problematic on the Arduino, though if you only use it in setup, as in this case, it is usually fine.

Thanks for the response,

So one more thing I am unclear on exactly.

I read that once a variable is created via malloc() and no longer needed, you should use free() to create room in the heap again. I have used malloc() to create room in the heap for the servos in the previous version of my code. Does that mean I have to use a free() command to remove it?

Basically, does the heap get erased every time I upload a new script?

Thanks,
Matt

Yes, the heap is reset everytime the arduino is reset - such as when you load a new script. It is not actually "cleared", but the new script just treats it as free space.

You can use malloc() in a semi static situation like this as long as you do it only once (which seems to be case) Then there is no need to use free because it basically a static allocation although its not known at runtime. For all other purposes, avoid dynamic memory.
What do you mean by script? The ardunio program itself? Or is labview sending some script to the arduino to be executed?

What do you mean by script? The ardunio program itself? Or is labview sending some script to the arduino to be executed?

No. Labview just sends the Arduino a byte array where the Arduino determines what to do with it.

The arduino has code uploaded to it (LIFA_Base) which initializes a whole bunch of variables in the void setup() area. In the void loop() area, it checks if there is a valid connection connection. If so, it takes the array labview sends it and checks which command is sent (there are ~40 that can be sent) and what values are associated with that command.

On labview side, there is a process to use a servo. You must attach it (where the malloc() declaration takes place), initialize it, then read/write data (This is in a while loop), and finally detach the servo (free();). The servo is detached once the the while loop stops. After detaching, the communication between labview and arduino is closed.

Matt

ukeri:
On labview side, there is a process to use a servo. You must attach it (where the malloc() declaration takes place), initialize it, then read/write data (This is in a while loop), and finally detach the servo (free();). The servo is detached once the the while loop stops. After detaching, the communication between labview and arduino is closed.

If it wasn't for the reference to using a servo I would assume this paragraph refers to code running on a PC. But I presume the servo is physically attached to the Arduino and therefore the paragraph probably means that one of the 40 commands that Labview sends requires the Arduino to do something with a servo. If that's true and if malloc() is called everytime that command is sent by Labview I suspect you will run out of memory at some stage. It would seem much easier to attach the servo using normal Arduino code in setup() and then it is available to be used as needed without any requirement for malloc().

...R

Robin2,

Yes, the servo is attached physically to the Arduino. It is being powered by a different power supply and has its control set by pin 9 (PWM output).

Technically, yes, it could run out of memory from the heap, but every time the labview code is run, it malloc() the servo, then runs the code runs, then free() the servo. Assuming that it was properly shut down. So while the code is running, the malloc() free() commands are only being sent once.

However, this is no longer my issue. I know that I need 2 servos in my code, so I can initialize the servos in the Arduino using the servo library (It's actually a custom servo library VarSpeedServo - a modified Servo library with speed control - Motors, Mechanics, Power and CNC - Arduino Forum with nothing removed, only a "slowmove" function was added. Everything else is the same).

I appreciate your concern Robin2, but as I said, it is no longer an issue for me :smiley:

Matt

The standard comment in C++ when it first came in was that you should never use malloc with C++ (it's only for use with pure C). With C++ it should be a call to new(). The best advice for the arduinos is don't use the heap at all. Lots of threads on the topic look for "String not string".

Mark

I've heard criticism about malloc() from embedded communities before, but is malloc() itself really the problem, or is it the likelihood of bad technique on the part of the user (say, by not calling free() or letting pointers fall out of scope, or whatevuh)? I.e., is avr-libc's malloc() known to be inherently buggy?

Just wondering 'cause I use malloc() quite a bit. But I'm also conscientious about when, how, and why. I use C outside of Arduino though, so proper memory management is just part of the contract as far as I'm concerned.

There are two very different things,

  1. malloc() and new() don't work to get along you should not use both in the same program. The same warning applies to STDIO and Streams if your working on (for example) a PC. STDIO is c only.

  2. There is a very big problem with C++ known a a memory leak. Basically the pointers to objects/data on the heap are lost before the memory is free()'ed. While PC's can get away with the odd leak the very small amount of memory available on the AVR's just can't deal with it. The result is a crash (at best).

  3. There is also a problem with the heap known as "memory fragmentation" . Google memory leaks and memory fragmentation.

Its best to make sure any instances to classes you create are global and other wise keep well clear of classes (this includes strings).

Mark

I understand memory fragmentation, but if you're doing something like this:

void loop () {
  ...
  doSomething();
  ..
}

void doSomething () {
  byte *data = malloc(BUFSIZE);
  ...
  ...
  free (data);
}

... there's no chance of leak, nor fragmentation. It's almost the same as declaring on the stack, except not deterministic the way compile-time variables are. Either way, memory will be allocated and free'd before returning from the function. Especially since embedded code is single-threaded (with the possible caveat of interrupt routines), I don't see fragmentation as a real concern in this use-case. (Now, with frequent realloc() to resize long-living arrays, sure...)

When you say "there is a known problem with C++", what exactly does that mean? C++ is a standard, and as such, can't really have "bugs" per se. Just ambiguities or conflicting rules. OTOH, compilers and libraries can of course have bugs, but that warning would apply to a certain compiler/library (and probably more likely a particular version). Bugs in malloc() would be pretty high visibility, and as such, I would imagine they would get patched sooner than later. Is it really "a thing" that gcc or avr-libc have had ongoing memory allocation issues that no one has yet fixed?

The new vs malloc() thing seems more a matter of style. Under the hood they do similar things, and malloc() is still a perfectly viable feature of the language. Which you choose seems to be more of a pragmatic debate than a technical one. You could accuse someone of being a pathological C programmer for using malloc() and stdio rather than new and iostream, but nevertheless, I would expect the code to compile and run with no degradation. It's still an option for a reason. :wink:

EDIT: I should strongly caveat this rant, in that it applies to allocation of blocks of memory, and not objects that require a constructor and have non-data members.

I don't know how well malloc() and new work together in this gcc environment, but I've worked in other C++ environments where they definitely weren't compatible - similarly, I've seen the problems that holmes4 mentioned when using stdio file pointers and streams together. Even if they do work OK together, it seems to me that it would be preferable to stick to one API or the other.

Whether malloc() and new work together or not, dynamically allocating and releasing heap is a bad idea on a platform with so little memory and such limited capability to manage that memory. I wouldn't use dynamic allocation at all unless it was necessary, and I don't see any benefit to using it in the example posted by SirNickity.

I'm not advocating mixing malloc/delete or new/free, nor stdio and iostream pointers. If you use one style, you must stick with it. Using pointers across APIs makes no more sense than trying to cast pointers for intrinsic types to other random types.

I just see no reason to avoid malloc() / free() in general. What is it about the example that you disagree with? For that matter, the example didn't even show why the memory was allocated, so I don't know how one could even pose a cogent argument for or against, except for the purpose of illustrating how it shouldn't lead to fragmentation -- which is all it was.

Again I'm told "you shouldn't" but without any explanation why. There may be a good reason, but without one, it just seems like cargo-cult knowledge to me. Regardless of how little or much memory exists, it can either be reliably allocated and tracked, or it can't. So if it can't, why? What's the weak link?

@Sirnickity

nor fragmentation.

Prove it - you will of course quote the code for the heap.

Mark

No, I won't. I'm not going to get into a pointless contest of who can post the most assembly instructions. It serves no purpose.

If you call a function that declares variables, those variables are dynamically allocated (in the stack) because you can't have all potential functions' variables simultaneously consuming memory. There are an infinite number of function calls and, accounting for recursion, you can't possibly have enough RAM to do that. So, dynamic allocation happens with or without discrete calls to malloc().

If you use new, it allocates memory dynamically and then does all the C-plus-plus-y stuff if the object has such a requirement.

From a logical standpoint, how are either of those scenarios different than allocating memory yourself?

If you allocate memory, and then all of that allocated memory is un-allocated before leaving that scope, there can be no fragmentation. The only way to cause fragmentation is to have blocks of memory freed between other allocations. If you're in a function call with a short-lived allocation, and nothing continues to exist outside the scope of that function, you're back to the same allocation of memory you had when you entered the function call. (Unless there's a bug in the compiler or the C libraries, of course.)

void loop () {

  // The amount of memory allocated here...
  doSomething();
  // ... should be the same as here

  ...

  // And likewise here...
  doSomethingElse();
  // ... and here
}

void doSomething () {
  int a;      // Just allocated two bytes
  int b;      // Just allocated two more
  ...
  return;     // Those four bytes are now freed
}

void doSomethingElse () {
  char *data = malloc(4);    //  Just allocated four bytes (and a pointer)
  ...
  free (data);    // Those four bytes are now freed
  return;         // And now so is the pointer
}

Where is fragmentation going to occur in either call?

However, if you do this:

byte *data;
byte *tmp;

uint8_t  data_sz = 1;
uint8_t  tmp_sz = 2;

void loop () {
  data = realloc(data, data_sz);
  tmp  = realloc(tmp,  tmp_sz);
  
  data_sz++;
  tmp_sz += 2;
}

Now you're going to fragment your RAM, because the allocation is persistent, and other memory blocks allocated later will prevent them from growing in-place, requiring the contents to be relocated elsewhere. This will continue to happen until the integers overflow, and then the locations will probably become permanent for the life of the program (as they'll have gotten as large as they can be), but it's a contrived example and in real life, the code would probably be more complex.

If I'm wrong, I welcome a rebuttal... I'm not trying to attack anyone here, but I feel if people are going to go around saying "Don't do this, it's bad", at least one person should have a legitimate argument for why. I don't need line numbers from compiler source code, nor even listings of dumped flash images. If it's a "known problem", that implies someone knows what the problem is. That, or it isn't a known problem. It's rumor and superstition.

servos = (VarSpeedServo*) malloc(2*sizeof(VarSpeedServo));
  for(int i=0; i<2; i++)
  {
    servos[i] = VarSpeedServo(); 
  }

Not to derail the deep philosophical discussion on the use of dynamic memory allocation on small microcontrollers, but THAT code just looks WRONG regardless.
Either "servos" is an array of pointers and the sizeof() should be sizeof(VarSpeedServo*), or it's an array of objects/structures and the cast is wrong, and maybe the assignment is wrong. Or maybe not. In C, this would all be very explicit and clear (to me, anyway), but I'm not sure how it's done in C++

ukeri:
Hello all,

Background to the question:
I have code that I'm trying to modify and there is a section where servos are initialized. The code is to control an arduino through LabView over serial communications. This is done by uploading a sketch to the arduino and then initializing stuff in LabView. My question is with the Servo initializing specifically,

servos = (VarSpeedServo*) malloc(2*sizeof(VarSpeedServo));

for(int i=0; i<2; i++)
  {
    servos[i] = VarSpeedServo();
  }




I have been searching around a lot to figure out what malloc() does.

http://snippets-r-us.com/

Post all of your code please.

Read this before posting a programming question

a legitimate argument for why

There's nothing inherently wrong with using malloc. As your examples illustrate, it can be safe to use and you can avoid memory fragmentation. Your suggested usage however, is a little atypical and doesn't appear to confer any advantage over declaring your objects on the stack.

Mostly, if you're using malloc, it's because you have to because you don't know at compile time how many objects you will need to create, nor what their lifetime will be. Those things will be determined by inputs at runtime. In this situation, it is risky to use malloc on an arduino because of the tiny ram, likelihood of heap fragmentation and lack of much error handling. You can still code around this if you know what you're doing, so it's not fair to say that you should never use it.

However, for new users and even experienced ones, use of malloc can lead to peculiar behaviour and apparently random problems that are very hard to track down. It makes it hard to be sure too, whether you've tested for long enough - will my always running system only fail after two weeks? IMHO, In 99% (or more) of cases, it's better to avoid its use and advise others to do the same