Why does this function crash a MEGA 2560?

HI,

I have written this function in a project. If I call it with small numbers and len = 3, it works. If I call it with small numbers and len = 5, the MEGA freezes...
Any ideas, anyone?

String leadingZero(String data, int len) {
  String result="";
  int i;
  if (data.length() < len) {
    for (i=0;i<(len-data.length());i++) {
      result += "0";
    }
  }
  result+=data;
  return result;
}

Don't use strings. The Arduino has no capability for garbage collection of objects like that.

Your function is hopelessly inefficient, even for a real computer.

The 'result' String is local to the leadingZero function which means it is allocated on the stack when you enter the function and it is freed when you leave. So you are returning a pointer to a non-existent String.
It's best not to use Strings at all because even a MEGA doesn't have a lot of spare RAM to allow much String manipulation.

Pete

If I call it with small numbers and len = 3, it works. If I call it with small numbers and len = 5, the MEGA freezes.

You don't call that function with numbers of any size. You call that function with Strings, of some unknown size. Some REAL examples would be good.

I agree with michinyon, though. It is highly unlikely that you need to use Strings at all.

    if (altitude < 60000) ea.drawText(225,86,'R'," "+leadingZero(String(altitude),5));

crashes,

    ea.drawText(465,86,'R',"  "+leadingZero(String(grs),3));

does not crash.

I don't know how to use char arrays for my stuff. I wrote a library for controlling intelligent TFT displays and my functions like drawText use Strings because otherwise just everything blows up in my face, because I have to display a ton of numerical data and I have no idea how to convert e.g. an integer into an array of char.

I don't know how to use char arrays for my stuff.

Then you need to learn. Converting altitude to a String so you can prepend leading 0s is silly, when the sprintf() function can do it for you. In fact, it can produce the whole string to draw without the need concatenate stuff in the function call.

Of course, exactly how to use sprintf() depends on the data types involved. You can either post all of your code, research the issue yourself, or head over to http://snippets-r-us.com for help. Your choice.

Even if you were using java or something, your program is not very good.

If you want to manipulate text on the arduino, you are probably going to have to learn how
traditional C-style char array strings work.

What's sprintf? It's not in the Arduino reference.

My code is here.

The sketch in question is here.

And the library I am writing is here.

What's sprintf? It's not in the Arduino reference.

The Arduino reference page is for stuff specific to the Arduino. sprintf() isn't.

You really need to put the crutches (the String class) away.

Is there any function that return a char array from in integer like char* function(int integer) or is there only functions which I have to give a char array as parameter to fill?
Where would I find the right documentation for sprintf? Google returns uncountable amounts of hits?

Is there any function that return a char array from in integer like char* function(int integer)

What does thins mean? Are you asking if there is a function that will contain a string that represents the integer value? The itoa() function does that.

Where would I find the right documentation for sprintf? Google returns uncountable amounts of hits?

No, it doesn't. It actually counts them for you. Just pick one. Really, it won't try to sell you a sprintf.

Please note that, at present, the String library has bugs as discussed here and here.

In particular, the dynamic memory allocation used by the String class may fail and cause random crashes.

I recommend reworking your code to manage without String. Use C-style strings instead (strcpy, strcat, strcmp, etc.).

Alternatively, install the fix described here:
http://arduino.cc/forum/index.php/topic,145765

PaulS:

Is there any function that return a char array from in integer like char* function(int integer)

What does thins mean? Are you asking if there is a function that will contain a string that represents the integer value? The itoa() function does that.

I don't know how to explain better. I'm no English native speaker. sprintf returns an integer, not a char array. I can't do something like this:

ea.drawText(100,100,'L',sprintf("%05d",altitude))

As far as I understand it, I have to declare some buffer variable first (which's size I need to know in advance), use sprintf to put the formatted string into the buffer and then use the buffer in drawText(). That's feels kinda cumbersome to me.

Yes you do, but you seem to have a pretty good idea of how large a buffer you need, as you are requesting a 5 digit number. You need to allow for the trailing string terminator, so a buffer of 6 bytes would be a good approximation, assuming you are sure the number will never be larger than 5 digits.

Unfortunately, that wasn't the only occurrence... As I wrote, I have to display a rather big amount of various numerical data, so I'm looking at some major rewriting... sigh

sprintf returns an integer, not a char array. I can't do something like this:

No, you can't. But, you can (and should) do:

char buffer[20];
sprintf(buffer, "L%05d",altitude);
ea.drawText(100,100, buffer);

As I wrote, I have to display a rather big amount of various numerical data, so I'm looking at some major rewriting... sigh

Quit moaning and get started. 8)

The fact that you started out in the wrong direction doesn't help you.

You may be able to write some functions to minimize the amount of work involved.

Try what I said in reply #11. That might fix the crashes.

In any case it shouldn't be hard to rewrite your function to work. Here's an example:

const char * leadingZero (const int data, const int len) 
  {
  static char buf [11];
  sprintf (buf, "%010d", data);
  return &buf [strlen (buf) - len];
  }  // end of leadingZero

void setup ()
  {
  Serial.begin (115200);
  Serial.println (leadingZero (42, 3));
  Serial.println (leadingZero (42, 4));
  Serial.println (leadingZero (42, 5));
  Serial.println (leadingZero (42, 6));
  }  // end of setup

void loop () {}

Test output:

042
0042
00042
000042

May I ask, why the 'const' as the type and in the parameters. I'm asking because I tried to write a function that returns a char array before and it didn't work.

The const just means you promise not to change it (the value is read-only).

I don't know how you tried to return the char array, but if it was a local automatic variable then it will have been allocated on the stack and the content becomes undefined as soon as the function returns.

I tried it basically like in that example, just without the 'const' and the 'static'. With ints and chars that works...