0

I'm using a customised C++ implementation of ArrayList based on the method found in Processing. The original code is by Obed Isai Rios, but I've added a version to Github with more explicit file structure. The arraylist is appended to by the add_string_item method, which works ok in the format arraylist->add_string_item("text string") but fails when the same input is a String variable. The following script illustrates:

#include "ArrayList.h"
void setup(){
  ArrayList *list = new ArrayList("text1");
  list->add_string_item("text2");
  String str = "text3";
  list->add_string_item(str);
}
void loop(){}

This fails on the last line with error message:

no matching function for call to 'ArrayList::add_string_item(String&)'

sketch_aug24b.ino: In function 'void setup()':
sketch_aug24b:7: error: no matching function for call to 'ArrayList::add_string_item(String&)'
/Users/robinedwards/Documents/Arduino/libraries/ArrayList/ArrayList.h:17: note: candidates are: void ArrayList::add_string_item(char*)

I'm not familiar with C++ so can't figure out why this method accepts a string but not when assigned to a String object str. I'm pretty sure it's because I need to coerce to char* but not sure how to do this. I've tried toCharArray without success, although this seems the right direction. Very grateful for any assistance.

ArrayList.cpp code:

#include "Arduino.h"
#include "ArrayList.h"

ArrayList::ArrayList(char* init){
  stringlist = (char**)malloc(10*sizeof(char*));
  stringlist[0] = init;
  this->size = 1; 
}

ArrayList::~ArrayList(void)
{
}

void ArrayList::add_string_item(char* item){
  char **neulist = (char**)malloc((size+1)*sizeof(char*));
  for(int i=0; i<size; i++){
    neulist[i] = stringlist[i];
   }
   //
   neulist[size] = item;
   stringlist = neulist;
   size = size + 1;
}

void ArrayList::set_string_item(char* item, int index){
  stringlist[index] = item;
}

void ArrayList::remove_selected_item(int index){
  char **neulist = (char**)malloc((size-1)*sizeof(char*));
  //From Begining
  for(int i=0; i<index; i++){
    neulist[i] = stringlist[i]; 
  }
  //From next Index  
  for(int i=index; i<=size-1; i++){
    neulist[i] = stringlist[i+1];
  }
  //free(matrix);
  stringlist = neulist;
  size = size - 1;
}

void ArrayList::empty_list(){
   size = 1;
   char **neulist = (char**)malloc((size)*sizeof(char*));   
   stringlist = neulist;
   stringlist[0] = "EMPTY";
}

void ArrayList::display_string_list(){
   Serial.begin(9600);
  for(int i=0; i<size; i++){
    Serial.println(stringlist[i]);
   }
}

char** ArrayList::get_stringlist(){
  return this->stringlist;
}

char* ArrayList::get_item(int index){
  return this->stringlist[index];
}

void ArrayList::set_stringlist(char** stringlist){
  this->stringlist = stringlist;
}

int ArrayList::get_size(){
  return this->size;
}
2

In theory, there's no reason why you shouldn't be able to call it by using toCharArray(). You would need to call it like this:

String str = "text3";
char * buf = new char[str.length()+1];
str.toCharArray(buf, str.length()+1);

list->add_string_item(buf);

That allocates a char buffer, copies the string data into it, then passes that buffer pointer to the list to be stored. Note that the buffer is one character larger than the string, as it needs to add a null terminator at the end.

However, there is a major problem with the rest of your code, which could eventually cause your Arduino to crash or do other strange things (depending on how much you use the list object).

Unlike Java, C++ is not a garbage-collected language, meaning it won't automatically clean-up memory for you. If you call new or malloc() to allocate heap memory, you have to call delete or free() (respectively) when you're finished with it to deallocate it.

Simply overwriting a pointer with another call to malloc() is not enough; it results in a memory leak. This means the block of memory it was previously using is lost, and cannot be reused again as long as the program is running. On a platform like Arduino, which has limited memory, you can very quickly run out.

Fixing the design of your class is probably beyond the scope of an answer on this site. I would strongly recommend working through some C++ tutorials (of which there are hundreds online).

As a side note, you should generally use new/delete instead of malloc()/free(). It doesn't make much difference when you're using arrays of char or char*, but it's important if you want to allocate class instances.

  • Awesomely helpful :) The toCharArray fix works, but you're right it does crash the arduino after a while. Think I'll revert to array methods until I find time to rework the library.. – geotheory Aug 26 '14 at 10:04

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.