EffegiWeb EffegiWeb - 9 months ago 45
C++ Question

Overloaded Methods in a class (arduino)

Header code

/*
* MngCommunication.h
*
* Created on: 26 gen 2017
* Author: Giuliano
*/

#ifndef _MNGCOMMUNICATION_H_
#define _MNGCOMMUNICATION_H_

// ------------------------- N.B. MngCommunication is a Singleton class!!! ----------------------------
#if (ARDUINO < 100)
#include <WProgram.h>
#else
#include <Arduino.h>
#endif

class MngCommunication
{
public:
static MngCommunication* getInstance();


size_t LogLine(const __FlashStringHelper *ifsh, boolean end=false);
size_t LogLine(const String &str, boolean end=false);
size_t LogLine(const char str[], boolean end=false);
size_t LogLine(const unsigned char n, boolean end=false);
size_t LogLine(const int n, boolean end=false);
size_t LogLine(const unsigned int n, boolean end=false);
size_t LogLine(const long n, boolean end=false);
size_t LogLine(const unsigned long n, boolean end=false);
size_t LogLine(const double n, boolean end=false);
size_t LogLine(const Printable&str, boolean end=false);

protected:
static MngCommunication* _inst_;
MngCommunication();
};

#endif /* MNGCOMMUNICATION_MNGCOMMUNICATION_H_ */


C++ code

/*
* MngCommunication.cpp
*
* Created on: 26 gen 2017
* Author: Giuliano
*/

#include <string.h>
#include "MngCommunication.h"


MngCommunication* MngCommunication::_inst_ = NULL;


MngCommunication::MngCommunication()
{
Serial.begin(57600);

}


MngCommunication* MngCommunication::getInstance()
{
if (_inst_ == NULL) _inst_ = new MngCommunication;

return _inst_;
}

//--------------------------------------------------------------------
//--------------------------------------------------------------------
// ------------------------ LOGGING FUNCTION -------------------------
//--------------------------------------------------------------------
//--------------------------------------------------------------------
boolean started=false;

inline size_t startLine(void)
{
static char timebuffer[8];
size_t sz = 0;

sprintf(timebuffer,"%08lu", millis());

sz += Serial.print("#L-");
sz += Serial.print(timebuffer);
sz += Serial.print("-");
started=true;
return sz;

}

inline size_t endline(void)
{
started = false;
return Serial.write("\r\n");
}

size_t MngCommunication::LogLine(const __FlashStringHelper *ifsh, boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}

sz += Serial.print(ifsh);

if (end)
{
sz += endline();
}


return sz;
}

size_t MngCommunication::LogLine(const String &str, boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}

sz += Serial.print(str);

if (end)
{
sz += endline();
}

return sz;
}


size_t MngCommunication::LogLine(const char str[], boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}

sz += Serial.print(str);

if (end)
{
sz += endline();
}

return sz;
}





size_t MngCommunication::LogLine(const unsigned char n, boolean end)
{
return LogLine((unsigned long) n, end);
}


size_t MngCommunication::LogLine(const int n, boolean end)
{
return LogLine((long) n, end);
}

size_t MngCommunication::LogLine(const unsigned int n, boolean end)
{
return LogLine((unsigned long) n, end);
}


size_t MngCommunication::LogLine(const long n, boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}

sz += Serial.print(n);

if (end)
{
sz += endline();
}

return sz;
}

size_t MngCommunication::LogLine(const unsigned long n, boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}

sz += Serial.print(n);

if (end)
{
sz += endline();
}

return sz;
}



size_t MngCommunication::LogLine(const double n, boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}

sz += Serial.print(n);

if (end)
{
sz += endline();
}

return sz;
}

size_t MngCommunication::LogLine(const Printable&str, boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}

sz += Serial.print(str);

if (end)
{
sz += endline();
}

return sz;
}


If I use
LogLine()
function with string or char buffers, all is OK. e.g.:

MngCommunication* Comm;

Comm = MngCommunication::getInstance();
Comm.LogLine("this ");
Comm.LogLine("is ");
Comm.LogLine("a ");
Comm.LogLine("test!!! ", true);


The strange is the call with number:
if i call
LogLine()
with number e.g.:

MngCommunication* Comm;

Comm = MngCommunication::getInstance();
Comm.LogLine(mills());


code execution is OK. but a second call, with number or string, reboot Arduino. The same is if i call the function first with string and then with number. e.g.:

MngCommunication* Comm;

Comm = MngCommunication::getInstance();
Comm.LogLine("this ");
Comm.LogLine("is ");
Comm.LogLine("a ");
Comm.LogLine("test!!! ");

Comm.LogLine("time= ");
Comm.LogLine(mills());

Answer Source
static char timebuffer[8];
sprintf(timebuffer,"%08lu", millis());

First of all this buffer is too small. There has to be space for the string terminator (zero byte), so you have a buffer overflow which can cause all sort of strange effects.

This buffer should be at least 11 bytes long. 10 bytes for the max number (32 bit) and one for the string terminator.

I suppose mills() was a typo?

Do you have the same problem when using a constant value, like Comm.LogLine(123);?

And what if you call:

Comm.LogLine(123, true);
Comm.LogLine(456);