Hello everyone! About a week I am having a nasty bug in my working application. After researching I've found that the bug is corresponding to memory allocation. Below I am going to show the logic (in general).
The problem is that at the time to display(), the data in cl1->inp_data or in cl2->buf becomes broken (depends on input).
Any idea what I may doing wrong violating integrity of arduino's sram? Thanks!
Example:
main.cpp
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#include "../lib/class1/class1.h"
#include "../lib/class2/class2.h"
using namespace std;
Adafruit_PCD8544 display = Adafruit_PCD8544(4, 6, 5, 2, 3);
Class1 cl1 = Class1(A0);
Class2 cl2 = Class2(&display, &cl1);
const uint8_t img[] PROGMEM = {0x01, 0xfc, 0x3f, 0x80, 0x01, 0xfc, 0x3f, 0x80};
void setup() {
Serial.begin(9600);
pinMode(7, OUTPUT);
digitalWrite(7, LOW);
display.begin();
display.setContrast(50);
display.setRotation(0);
display.clearDisplay();
if(!cl1.init() || !cl2.init()) {
display.println("Failed to initialize");
display.display();
delay(5000);
}
}
void loop() {
display.clearDisplay();
cl1.doCheck();
switch(cl2.getState()) {
case 0:
cl1.addImg(img, "image");
cl1.regInput(10, "some text");
// do something
break;
case 1:
cl1.regInput(5, "some text");
// do something
break;
default:
// do something
break;
}
cl2.display();
delay(2000);
}
class1.cpp:
#include <Arduino.h>
#include "class1.h"
using namespace std;
Class1::Class1(uint8_t port) {
inPort = port;
}
bool Class1::init() {
bool statusFail = false;
pinMode(inPort, INPUT);
void * mem = calloc(5, sizeof(char));
if(mem == nullptr) {
statusFail = true;
} else {
inp_data = (char *)mem;
}
void * mem1 = calloc(5, sizeof(char));
if(mem1 == nullptr) {
statusFail = true;
} else {
op_data = (char *)mem1;
}
return statusFail;
}
void Class1::doCheck() {
// collecting input data
state = 0;
}
void Class1::regInput(uint8_t input_length, char const * text) {
if(strlen(inp_data) < input_length) {
size_t s = input_length * sizeof(char);
void * mem = realloc(inp_data, s);
memset(mem, '\0', s);
if(mem == nullptr) {
Serial.println("ERROR");
}
inp_data = (char*)mem;
}
// do something
for(uint8_t i = 0; i < strlen(text); i++) {
*(inp_data + i) = *(text + i);
}
}
char * Class1::getInput() {
return inp_data;
}
uint8_t Class1::getState() {
return state;
}
void Class1::addImg( uint8_t const *img, char const * name) {
struct1 st1;
st1.name = name;
st1.img = img;
contents.push_back(st1);
}
class1.h
#ifndef CL1
#define CL1
#include <ArduinoSTL.h>
class Class1 {
public:
Class1(uint8_t port);
~Class1() {
free(inp_data);
free(op_data);
};
bool init();
void doCheck();
void regInput(uint8_t input_length, char const * text);
char * getInput();
uint8_t getState();
void addImg( uint8_t const * img, char const * text);
private:
uint8_t inPort;
char * inp_data,
* op_data;
uint8_t state;
struct struct1 {
const uint8_t * img;
const char * name;
};
std::vector<struct1> contents;
};
#endif
class2.cpp
#include "class2.h"
using namespace std;
Class2::Class2(Adafruit_PCD8544 * lcd, Class1 * cl1) {
obj_lcd = lcd;
obj_class1 = cl1;
}
bool Class2::init() {
bool statusFail = false;
buf = (char*)calloc(100, sizeof(char));
if(buf == nullptr) {
statusFail = true;
}
return statusFail;
}
uint8_t Class2::getState() {
// do something assuming cl1->status value
return obj_class1->getState();
}
void Class2::display() {
// displaying input data from Class1
strcpy(buf, obj_class1->getInput());
obj_lcd->setTextSize(1);
obj_lcd->setTextColor(BLACK);
obj_lcd->setCursor(0, 0);
obj_lcd->println(buf);
obj_lcd->display();
}
class2.h
#ifndef CL2
#define CL2
#include "../class1/class1.h"
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
class Class2 {
public:
Class2(Adafruit_PCD8544 * lcd, Class1 * cl1);
~Class2() {
free(buf);
};
bool init();
uint8_t getState();
void display();
private:
Adafruit_PCD8544 * obj_lcd;
Class1 * obj_class1;
char * buf;
};
#endif