crash with array list

Hello all,

I'm trying to write a tiny array list class for my project but I must be missing something, I'm afraid I must have got something fundamental very wrong in my mind. I hope you can explain to me what I'm doing wrong.

This is my ArrayList class:

#include <stdio.h>
#include <stdlib.h>

template<class T> class ArrayList {

  private:
  
    int _size;
    int capacity;
    T *items;
    
    void expand( int new_capacity ) {
      T *new_items = (T*)malloc(new_capacity*sizeof(T));
      for (int i = 0; i < _size; i++) {
        new_items[i] = items[i];
      }
      if (items != NULL) {
        delete items;
      }
      items = new_items;
    }
    
  public:

    ArrayList() {
      _size = 0;
      capacity = 0;
      items = NULL;
      expand(3); /* initial capacity: 3 */
    }
    
    ~ArrayList() {
      if (items != NULL) {
        delete items;
      }
    }
    
    void add( T item ) {
      if (_size > 2*capacity/3) {
        expand(2*capacity);
      }
      items[_size++] = item;
    }
    
    T get( int index ) {
      return items[index];
    }
    
    int size() {
      return _size;
    }

};

This is a very tiny array list, the intention for now is to only add items and expand if necessary. Also I want this to be templated so I can store whatever type of object I want.

Then in my loop()'s code I do this:

void loop() {
  Serial.println("loop");
  ArrayList<String*> myarray;
  myarray.add(new String("testing"));
  Serial.println(myarray.size());
  delay(1000);
}

The above seems to work. But if I try to not dynamically allocate the strings, but rather create them in the stack, like this:

void loop() {
  Serial.println("loop");
  ArrayList<String> list;
  list.add(String("one"));
  list.add(String("two"));
  list.add(String("three"));
  Serial.println(list.size());
  delay(1000);
}

Then kaboom, the program iterates for a couple of loops then crashes, also I get some strange characters in the serial monitor.

Can anyone explain to me what is going wrong with the second one?

Thanks!

You are aware how much RAM is available? Dynamic memory allocation is best avoided completely.

If you are careful not to exceed the available RAM, then what is wrong with dynamic allocation?

But, just to stay on topic, why is the 2nd case failing? (which by the way is the one that is NOT using dynamic allocation)

It's using the String constructor, that does use dynamic allocation, and very badly. I would suggest that is the cause of your problem.

Your class has a destructor which deletes the array of pointers. Might be a good idea to delete the data each pointer points too as well.

Edited start of message, read wrong section

If you are careful not to exceed the available RAM, then what is wrong with dynamic allocation?

Memory fragmentation.

You can be well within the amount of available memory when you malloc(), but if you try to allocate a block that's bigger than the largest contiguous free block in the heap, then it will allocate to the end of the heap and crash into the stack.