Arduino pointer-to-function broken? Compiler Issue?

Hi there!
I am having very strange crashes in when using a combination of Messenger, the SD library and function pointers. The sketch is a bit involved to upload, but I have a couple of things that are, definitely, not right (or I am doing something very silly or there's something I don't understand)

The function pointers look like this:

typedef void (* HandlerFuncPtr)() ; // this is a typedef to the messenger functions
HandlerFuncPtr functions[4] = {DisplayBatteryData, TimeDate,SDInfo,ReadFile};

with all those functions being global static ones.

I compile my sketch with this function:

void messageCompleted()
{
    for (unsigned char c = 0; c < sizeofarray(commands); c++)
    {
        if(message.checkString(commands[c]))
        {
            functions[c]; //Were we go
            return;
        }
    }
    Serial << "ERROR: Couldn't parse message, commands are" << endl;
    ListCommands();
}

Which obviously does nothing at the funcion

, because it is not calling the function itself.

What is funky about it, is that, if I add "()" behind
[code]functions[c](); [/code]
the program goes from 18960 bytes to 21070 and becomes super unstable.

Any ideas?

What type is commands? If it isn't an array of bytes, this: sizeofarray(commands) may be giving you trouble. If it isn't evaluating to four, you'll be overrunning your functions array. That would definitely cause some serious instability.

the program goes from 18960 bytes to 21070 and becomes super unstable.

I'm guessing you're using too much RAM.
But that's just a guess.

Which obviously does nothing at the funcion

, because it is not calling the function itself.[/quote]

True.

[quote]What is funky about it, is that, if I add "()" behind
the program goes from 18960 bytes to 21070 and becomes super unstable.[/quote]
You are now actually calling the functions, so, of course the size goes up.

That your sketch becomes unstable is a surprise. Does it often wobble around and fall over? How can you see that happening?

Developing this much code without an understanding of you are doing is definitely classified as very silly. There is probably a lot that you don't understand.

There is a lot we don't understand, like how your code can become unstable and fall over.

Perhaps you need to post all of your code, and explain what exactly it is doing wrong.

wildbill:
What type is commands? If it isn't an array of bytes, this: sizeofarray(commands) may be giving you trouble. If it isn't evaluating to four, you'll be overrunning your functions array. That would definitely cause some serious instability.

Commands is a list of char*, such as:

char* commands[4]           = {"battery", "timedate","sdinfo","readfile"};

In any case, sizeofarray does take care of granularity, though;

template<typename T>
int sizeofarray(T& obj)
{
        return sizeof(obj)/sizeof(obj[0]);
};

the result is always four :slight_smile:

What is funky about it, is that, if I add "()" behind
the program goes from 18960 bytes to 21070 and becomes super unstable.

You are now actually calling the functions, so, of course the size goes up.

Yeah, I didn't think about the compiler optimizing the functions away.

That your sketch becomes unstable is a surprise. Does it often wobble around and fall over? How can you see that happening?

It sometimes hangs up, sometimes reboots, sometimes displays corrupted data (as, if I try to list the array of char* I see a partly corrupted result.

The sketch is a bit involved to upload, but I have a couple of things that are, definitely, not right (or I am doing something very silly or there's something I don't understand)

Developing this much code without an understanding of you are doing is definitely classified as very silly. There is probably a lot that you don't understand.

Sorry, I didn't quite get that comment. I mean that certain behaviors of the program don't make sense. I am not quite a newbie, if that's your assumption :slight_smile:

Perhaps you need to post all of your code, and explain what exactly it is doing wrong.

The main issue that I have is that it doesn't seem to happen with any one system. Only when I use function pointers AND access the SD card do I get issues, it is a bit maddening to be frank.
But if you think that will help and somebody will read it, sure.

But if you think that will help and somebody will read it, sure.

We can also check out AWOL's quite possibly correct suspicion that you are running out of SRAM, so, yes, post the code.

Yeah, I've been thinking about that too, the fact that things only fail when I put several systems together has made me think.
Eventually I've figured out it was a SD information function that was designed to open the SD card from scratch (after it was already open) which was leading to a couple of bad bugs AND the out of memory.
I have added a freemem() function to track things down, I am running at 200 bytes, which I find very, very scary :frowning:

Any string literals floating in SRAM should find their own places in the FLASH now.

liudr:
Any string literals floating in SRAM should find their own places in the FLASH now.

Hi liudr, what do you mean exactly? You are talking about the flash memory I guess, is that something the compiler decides before the code runs? So in theory if can increase the string sizes and have no changes in the available RAM, am I right?

Serial << "ERROR: Couldn't parse message, commands are" << endl;

That string there looks like it should go into flash, because it is a constant (and it does), but it get copied to before "main" runs.
If you have lots of strings like that, they'll gobble up RAM.

What do you mean by "it gets copied to before "main" runs?
...and, it sounding like a bad thing, how do I avoid it? :slight_smile:

I didn't see anyone mention this explicitly:

functions[c]; //Were we go

This will not call the function; it just evaluates to the value of the function pointer. Because that is evaluated but never used, the compiler/linker can actually optimize out the entire functions array, as well as the functions that go into that array! Therefore your program is small.

Thus, when you add the parens after the function pointer, your program actually does what I think it is you want -- use the function pointer table as a vector of functions to call in response to a particular command.

jwatte:
I didn't see anyone mention this explicitly:

functions[c]; //Were we go

This will not call the function; it just evaluates to the value of the function pointer. Because that is evaluated but never used, the compiler/linker can actually optimize out the entire functions array[...]in response to a particular command.

Agreed, I ended up mentioning it myself :slight_smile:
thanks for the input!

Sorry, it should have read 'it gets copied to RAM before 'main' runs'.

How to avoid that?
Use 'PROGMEM'.

I am not quite sure on how to use PROGMEM in something like Serial << "message" << endl;

Moving Serial << "mess" to Serial.println("mess") doesn't seem to affect available RAM.

I am not quite sure on how to use PROGMEM in something like
Code:
Serial << "message" << endl;

Me neither.
That's one of the reasons I avoid streaming, and prefer the serial print methods.

Moving
Code:
Serial << "mess" to
Code:
Serial.println("mess") doesn't seem to affect available RAM.

I can't imagine why you thought it could.

[quote]I am not quite sure on how to use PROGMEM in something like 
Code:
Serial << "message" << endl;
[/quote]
Me neither.
That's one of the reasons I avoid streaming, and prefer the serial print methods.

Well, I guess I'll have to give up streaming for memory in most cases if I can't find a way (and I'll let you guys know if I do)

Moving
Code:
Serial << "mess" to
Code:
Serial.println("mess") doesn't seem to affect available RAM.

I can't imagine why you thought it could.

Me neither, I was thinking about your comment of literals that should "finding their way to flash", I guess you meant "find their way with a bit of a push" :slight_smile:

Thanks for all the help!

I'm not sure if you founds this already, but here's the information about program memory: http://arduino.cc/playground/Main/PROGMEM

Yeah, I saw that some time ago, it doesn't seem super user-friendly though. I wonder why the compiler doesn't do it automatically (controlled with a compiler option or a #define or a #pragma or something)