1

I know it is not a good practice to use the new command to dynamically create data, however, if I would never use the delete, would it result in memory gaps/other problems?

Background

The reason I need to create instances dynamically, is that I want to test my application first on a PC. And I want for several classes to have more properties for the PC version than for the Arduino version (for example, to store names, or information for the PC GUI to display). The PC version classes will be inherited from the Arduino (real) classes, but with added properties.

In some classes I need to build up a list, and I cannot use a type with hardcoded values to fill an array.

Example:

I have a LightSetup class that has a list of Pars (which are LED lights):

class LightSetup
{
protected:
    Par* _pars[NR_OF_PARS];

Par is the Arduino/real version, to fill in these I need:

LightSetup::LightSetup()
{
    for (int n = 0; n < NR_OF_PARS; n++)
    {
        _pars[n] = new Par(1 + 8 * n);
    }
}

In the PC version, instead of new Par, I use new TestPar. And in the header I cannot define it without a pointer like this:

    Par _pars[NR_OF_PARS];

Otherwise it cannot contain TestPar instances.

  • 1
    You could avoid the new-delete-heap-issue by using a template class. Here is an example: github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/… – Mikael Patel May 8 at 10:54
  • @MikaelPatel Thanks for this comment, it also sounds like a good idea ... forgot about templates (having used it 20 years ago for the last time ;-) ). – Michel Keijzers May 8 at 12:14
  • 1
    Another example is this GPIO template class that compile digitalRead/Write to a single instruction: github.com/mikaelpatel/Arduino-GPIO/blob/master/src/Hardware/… – Mikael Patel May 8 at 17:00
  • 1
    I have to say, when I first read the title I was pretty set on the answer being "It is never acceptable" but you have given me an interesting scenario to think about. It's an unusual case but valid. – Kelly S. French May 8 at 18:47
  • 1
    Here is another example: Java allows you to pre-allocate a block of memory (starting heap size?) at load-time for exactly the same reason, to cut down on memory allocation during execution. This would actually make for a good general StackOverflow question for the general case and I'd encourage you to post about it. – Kelly S. French May 9 at 15:05
2

Sure. Using new or malloc to set things up initially is really no different to static allocations. There is nothing inherently bad with using malloc or new, only in using it repeatedly with free or delete.

Allocating a block of heap memory and keeping it allocated for the rest of eternity does not cause heap fragmentation. It's only repeated allocation and deallocation of variable sizes (such as String causes) that start to create problems. Allocating at the start of your program and leaving it allocated, as long as you don't allocate too much, of course, is not a problem.

  • Thanks for the confirmation. The only disadvantage I can see is that the used memory is not calculated to the global variables in the Arduino IDE. – Michel Keijzers May 8 at 9:23
  • 1
    Yup. Hence the nudge to watch out that you don't allocate too much :) – Majenko May 8 at 9:30
  • Maybe I will for debugging purposes show the amount of reserved memory after the new statements. – Michel Keijzers May 8 at 9:35
2

In the destructor you would need

LightSetup::~LightSetup()
{
    for (int n = 0; n < NR_OF_PARS; n++)
    {
        delete _pars[n];
    }
}

and every time you replace a _pars you need to delete the old one. This can be done automatically by using unique_ptr.

However for your purpose it sounds like a #if is better suited to differentiate at compile time which type you actually store inside that array.

#if ON_ARDUINO
    Par _pars[NR_OF_PARS];
#else
    TestPar _pars[NR_OF_PARS];
#endif
  • Well, the destructor will never be called, since in my Arduino application the loop will run forever, so it's not an issue. But I upvoted it for the last part, maybe that's even better than the new command (although it clutters up code a bit). However, if this is the only change, it is easier. Thanks – Michel Keijzers May 8 at 9:49
  • 1
    I agree with @ratchet on the #if as the case you describe isn't about dynamic typing but rather a difference in platforms. Unless you need the same binary to run on both platforms (if even possible) you would be better served by conditional compilation. This also removes the need to bother with a destructor. – Kelly S. French May 8 at 15:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.