Dynamic allocation of an array within a structure

How can I dynamically allocate an array that is in a structure.

Here is my code.

#define CAPACITY  4
#define LEN       2

typedef struct aStruct_s
{
  int x;
  int arr[LEN];
} aStruct_t;

void setup() {
  Serial.begin(9600);

  aStruct_t* aStruct = (aStruct_t*) malloc( sizeof(aStruct_t) * CAPACITY );

  aStruct[3].arr[1] = 255;
  Serial.println( aStruct[3].arr[1] );
}
  
void loop() { }
typedef struct aStruct_s
{
  int x;
  int * arr;
} aStruct_t;

...

  aStruct_t* aStruct = (aStruct_t*) calloc( CAPACITY, sizeof(aStruct_t) );
  aStruct[0].arr = (int*) calloc( 42, sizeof(int) );
  aStruct[1].arr = (int*) calloc( 17, sizeof(int) );
  ...

Thanks, Coding Badly, but could you explain your code.

What is the meaning of "42" and "17" in the calloc()? To me, that means allocate memory to 42 ints and 17 ints. Maybe you arbitrarily selected 42 and 17 as an example of a ragged array, with different arr lengths.

Also, is a aStruct[ index ].arr = ... statement needed for every row of the aStruct array? Is there way to collapse those multiple statements into only one statement?

I read somewhere that dynamic allocation is not recommended for the simpler Arduino boards. Does a simple board, the UNO for instance, support dynamic allocation? Are there issues with doing so?

Don't double post

...R

sthudium:
What is the meaning of “42” and “17” in the calloc()? To me, that means allocate memory to 42 ints and 17 ints.

Correct.

aStruct[0].arr[0] through aStruct[0].arr[41] are valid.

aStruct[1].arr[0] through aStruct[1].arr[16] are valid.

Also, is a aStruct[ index ].arr = … statement needed for every row of the aStruct array?

Yes.

Is there way to collapse those multiple statements into only one statement?

for ( int i=0; i < CAPACITY; ++i )
{
  aStruct[i].arr = (int*) calloc( 3*(i+1), sizeof(int) );
}

aStruct[0].arr has 3*(0+1) = 3 elements.

aStruct[1].arr has 3*(1+1) = 6 elements.

aStruct[2].arr has 3*(2+1) = 9 elements.

Etcetera.

Threads merged.

sthudium: I read somewhere that dynamic allocation is not recommended for the simpler Arduino boards.

There are risks. A great example: What is the recovery path if an allocation fails?

In the code I posted above I ignore failed allocations. That is a terrible idea. But what should be done if calloc returns NULL?

Does a simple board, the UNO for instance, support dynamic allocation?

Yes. (You could have easily tried it yourself to answer the question. ;) )

Are there issues with doing so?

Two big ones: 1. Recovery path for failed allocations; 2. Fragmentation.

Thanks, Coding Badly. It sound like dynamic allocation should be avoided unless it is really necessary, like the case where object sizes are unknown before run-time.

The reason I am interested in dynamic allocation is for readability. It seems to me that putting the array size in an initialization function is easier to understand than searching for #define statements that are located in who knows where. But that's probably a newbie error.

sthudium:
It sound like dynamic allocation should be avoided unless it is really necessary,

And even when it is IMHO because the Arduino does not have sufficient spare memory to absorb problems.

Just allocate enough memory for the worst (biggest) case. Because an Arduino only runs one program the memory that might be available from a smaller allocation can’t be used.

…R

A number of people in here advised me that it is not a good idea to to use the heap (calloc, malloc, alloc, new) extensively in an arduino sketch.

Because it results in heap fragmentation over a period of day or weeks and may result in your sketch crashing.

It is better to just allocate variables as globals and locals etc.

My (perhaps naive) way of looking at it is that whether you define global (or local static) storage at compile time or allocate it dynamically, it still occupies the same amount of space at the “low” end of the RAM map. Thus, either technique affords the same amount of “margin” against the stack colliding in to it as function calls take place and local variables are allocated at run time. The advantage of the former technique is that you get information about that margin from the compiler.

Of course, the above assumes you don’t do a bunch of malloc() / free() cycles and fragment the memory.

gfvalvo: My (perhaps naive) way of looking at it is that whether you define global (or local static) storage at compile time or allocate it dynamically, it still occupies the same amount of space...

Nope. Heaps have overhead.

[quote author=Coding Badly date=1515783665 link=msg=3561252] Nope. Heaps have overhead. [/quote] Makes sense. How much? How does overhead grow with number and size of blocks allocated?

On an Arduino board, why would a calloc or malloc fail to allocate on-board memory? I presume the only reason would be that the memory is full, possibly due to memory leaks that result from poor code design.

sthudium: On an Arduino board, why would a calloc or malloc fail to allocate on-board memory?

When you ask it to malloc() more memory than the heap has available.

gfvalvo: Makes sense. How much?

No idea.

But the source code is available on Github and Savannah. Or, a bit of black box testing should reveal the answer.

sthudium:
On an Arduino board, why would a calloc or malloc fail to allocate on-board memory? I presume the only reason would be that the memory is full, possibly due to memory leaks that result from poor code design.

I think you are still applying a PC / Operating System mindset. The Arduino has nothing to prevent you doing foolish things like trying to allocate memory that is already in use.

…R

What is the best way to build a library with user adjustable array dimensions? One way is to instruct the user of the library to modify the array in the library code. But is there a way to expose those internal dimensions to the client file so that the user does not need to modify the library code? Currently, the only way I know is to use dynamic allocation, but as seen above, that also has issues.

sthudium: What is the best way to build a library with user adjustable array dimensions? One way is to instruct the user of the library to modify the array in the library code. But is there a way to expose those internal dimensions to the client file so that the user does not need to modify the library code? Currently, the only way I know is to use dynamic allocation, but as seen above, that also has issues.

It has no issues if you allocate after checking whether there is enough memory available. The problems begin when you subsequently allocate more without freeing what you allocated, then free the original allocation. That leaves gaps which are the root cause of fragmentation.