Calculator Memory Issues

Hello, i tried making a small math expression parsing library, but it seems that i can only do one Parse, and then my Uno freezes, i'm fairly certain there are no leaks which makes me ask why its freezing, and i would appreciate if anyone is able to look into it. I am not yet very familiar with the C allocation functions, so please tell me if i used any of them wrong. Thank you!
52 Replies
Killed_By_Hydra
Best way to not have an issue is to not use c allocation especially in arduino they dont work in arduino and in microcontrollers the way they do with computers
Dimolade
DimoladeOP2w ago
Oh, should i just use fixed size arrays then?
Killed_By_Hydra
Im pretty sure arduino has an alternative anyways Wait for someone who knows what to do answer, i would use a fixed array but im sure theres a much better way.
Dimolade
DimoladeOP2w ago
Thanks!
Killed_By_Hydra
Microcontrollers have a different system of memory than computers, im not sure but i think they use really short paging. Like 100 bytes short And it pages by the instruction counter
pseud0
pseud02w ago
You can check if you have memory leaks by testing the free heap before and after the calculation. https://docs.arduino.cc/learn/programming/memory-guide/#sram-memory-measurement gives the code for AVR boards, which your Uno is if we're talking Uno R3.
Killed_By_Hydra
Can malloc even be used?
Dimolade
DimoladeOP2w ago
yup
pseud0
pseud02w ago
In extremely small cases, yes. Heap fragmentation can quickly become an issue. Same with excessive String() object creation.
Dimolade
DimoladeOP2w ago
alright im quickly gonna check some things with this and then ill come back with results!
Killed_By_Hydra
Whats the way to use it because i remember it worked way differently that on a computer
Dimolade
DimoladeOP2w ago
well thats weird, i actually gained SRAM after doing '=', it prints out once more when doing '=' (but the result doesnt for some reason), then becomes unresponsive, maybe it isnt a memory issue?
1+1
- SRAM left: 1468
2.000000
- SRAM left: 1480
- SRAM left: 1480
1+1
- SRAM left: 1468
2.000000
- SRAM left: 1480
- SRAM left: 1480
Killed_By_Hydra
Can you send the part of your code where you do the memory allocation?
Dimolade
DimoladeOP2w ago
What do you mean exactly? All malloc's are in calclib.hpp
Killed_By_Hydra
I mean send it like this
code
code
im on phone I cant look at the file
Dimolade
DimoladeOP2w ago
Alright the entire file?
Killed_By_Hydra
No just the part where your using malloc
Dimolade
DimoladeOP2w ago
theres 18 malloc's
Killed_By_Hydra
Nvm I dont even you can allocate 32 spaces, what pointer does it return when you do?
Dimolade
DimoladeOP2w ago
wdym?
Killed_By_Hydra
Whats the pointer that it returns?
Dimolade
DimoladeOP2w ago
what returns?
Killed_By_Hydra
Malloc(32)
Dimolade
DimoladeOP2w ago
let me check this is from the result
2.000000
2.000000
or what do you mean?
Killed_By_Hydra
Does it return that again when you repeat it? Rerun it
Dimolade
DimoladeOP2w ago
it does not return the same result after i run it again, after running '=' again it doesnt print and after one more it becomes entirely unresponsive.
Killed_By_Hydra
Malloc(32 Malloc(32 These two return different result? In a program alone with nothing else
Dimolade
DimoladeOP2w ago
uhh alright let me check
Killed_By_Hydra
How much ram does the ide say the board has? And how much are you allocating? (Assuming there isnt a memory leak)
Dimolade
DimoladeOP2w ago
2048 bytes nope this seems to work in a single program just fine.
char* malloc32()
{
char* e = (char*)malloc(32);
strcpy(e, "Hello, World!");
return e;
}

void setup()
{
Serial.begin(115200);
char* first = malloc32();
Serial.println(first);
free(first);
char* second = malloc32();
Serial.println(second);
free(second);
}

void loop()
{

}
char* malloc32()
{
char* e = (char*)malloc(32);
strcpy(e, "Hello, World!");
return e;
}

void setup()
{
Serial.begin(115200);
char* first = malloc32();
Serial.println(first);
free(first);
char* second = malloc32();
Serial.println(second);
free(second);
}

void loop()
{

}
in total from every malloc summed up or?
Killed_By_Hydra
Alright lets test something, allocate 2000 bytes. Does it freeze the board up like your program your trying to fix does? Summed up yeh The uno might not be freeing the memory Btw srry for making you do all of this im away from a computer rn and cant test anything myself If you want to wait thats okay
Dimolade
DimoladeOP2w ago
uhh somehow doesnt freeze?
void setup()
{
Serial.begin(115200);
Serial.println("Memory");
malloc(2048);
Serial.println(("Memory 2"));
}

void loop()
{

}
void setup()
{
Serial.begin(115200);
Serial.println("Memory");
malloc(2048);
Serial.println(("Memory 2"));
}

void loop()
{

}
Unless i did something wrong its fine
Killed_By_Hydra
Try to do more than 2048 Also check if its returning null
Dimolade
DimoladeOP2w ago
sure void setup() { Serial.begin(115200); Serial.println("Memory"); char* e = malloc(2000); if (e == NULL) { Serial.println("NOT memory 2"); } Serial.println(("Memory 2")); } void loop() { } 2000 isnt null, 2048 and above is null. there are alot of malloc's which are writing to the same pointer (freed before, basically im saying theres alot more mallocs then frees), do you want it anyway? im just gonna try the same calculator code on my mega, see if theres any difference, even tho i doubt it seems to not be memory related at all, my mega has the exact same result First prints out the valid result, then prints out nothing, then becomes unresponsive AFTER the third '=' which is interesting
Killed_By_Hydra
Huh Yeah i have no idea
Dimolade
DimoladeOP2w ago
me neither this is, extremely weird
Killed_By_Hydra
Ill try your code on a esp sometime today
Dimolade
DimoladeOP2w ago
its 8:44 pm for me
Killed_By_Hydra
2 here
Dimolade
DimoladeOP2w ago
2 pm?
Killed_By_Hydra
Yeh
Dimolade
DimoladeOP2w ago
alright, i might be asleep by the time you test, which is fine, so incase i will be asleep by then, goodnight. also its crazy how i managed to make it CONSISTENTLY unresponsive after 2 parsing's i mean, its also possible its not truly unresponsive, i still see the Serial led light up when i input something just no output so if you have an lcd that could help debug
Killed_By_Hydra
Serial issue maybe? Maybes its not the board freezing up?
Dimolade
DimoladeOP2w ago
Yeah thats a possibility If you have anything to test that thatd be great But then again, what would cause serial to freeze up?
Killed_By_Hydra
No idea @Dimolade btw sorry for making you wait im a bit busy I have to get my workspace setup before i can do anything
Dimolade
DimoladeOP2w ago
Its fine👍
jim lee
jim lee2w ago
Just a quick look, maybe this has been cought alreadey?
c++
~CalculatorResult() {
if (!success && errorMessage != NULL)
free(errorMessage);
if (strResult != nullptr)
free(strResult);
}
c++
~CalculatorResult() {
if (!success && errorMessage != NULL)
free(errorMessage);
if (strResult != nullptr)
free(strResult);
}
This is really rough to follow with all its combining and double negitives. Try..
c++
~CalculatorResult() {
if (errorMessage) free(errorMessage);
if (strResult) free(strResult);
}
// And be done with it.
c++
~CalculatorResult() {
if (errorMessage) free(errorMessage);
if (strResult) free(strResult);
}
// And be done with it.
Also, why structs? If you want to make classes, why not make classes? You also mix nullptr with NULL all over. Is there a reason for this? You sure that's a good idea? Oh one other thing. declaring variables and classes inside case statements is a very bad idea! I'm seen the compiler go completely batty doing that. Took forever to track it down.
Dimolade
DimoladeOP2w ago
I thought the only difference was the privacy of variables? Oh dang Alr ill try that
jim lee
jim lee7d ago
For allocating and re-allocating of memory. I use resizeBuff(). Saves a lot of typing. Bascally you declare a pointer, say.. for a c string, like you use.
c++
char *strBuff; // Declare the string buffer. (Pointer)
strBuff = NULL // Set it to NULL. (MUST DO THIS)
if (resizeBuff(55,&strBuff)) {
// Allocation's good. do stuff.
} else {
// Allocation failed. do other stuff.
}

// Then at any time you can reallocate it. As many times as you like.
if (resizeBuff(12,&strBuff)) {
// Allocation's good. do stuff.
} else {
// Allocation failed. do other stuff.
}

// To finally free it up, resize t 0.
resizeBuff(0,&strBuff);

// Here's the code copied out of the library.
//****************************************************************************************
// resizeBuff:
//****************************************************************************************


bool resizeBuff(int numBytes,uint8_t** buff) {

if(*buff) { // If we did NOT get passed in a NULL..
free(*buff); // We free the memory.
*buff = NULL; // Set the pointer to NULL.
}
if (numBytes>0) { // If we got a positive non zero value..
*buff = (uint8_t*)malloc(numBytes); // We attempt allocate that number of bytes.
return *buff != NULL; // And we return true for non NULL result (non-NULL = Success)
}
return true; // In this case we were not asked to allocate anything so it was a success.
}

bool resizeBuff(int numBytes,char** buff) { return resizeBuff(numBytes,(uint8_t**)buff); }

bool resizeBuff(int numBytes,void** buff) { return resizeBuff(numBytes,(uint8_t**)buff); }

bool resizeBuff(int numBytes,float** buff) { return resizeBuff(numBytes,(uint8_t**)buff); }
c++
char *strBuff; // Declare the string buffer. (Pointer)
strBuff = NULL // Set it to NULL. (MUST DO THIS)
if (resizeBuff(55,&strBuff)) {
// Allocation's good. do stuff.
} else {
// Allocation failed. do other stuff.
}

// Then at any time you can reallocate it. As many times as you like.
if (resizeBuff(12,&strBuff)) {
// Allocation's good. do stuff.
} else {
// Allocation failed. do other stuff.
}

// To finally free it up, resize t 0.
resizeBuff(0,&strBuff);

// Here's the code copied out of the library.
//****************************************************************************************
// resizeBuff:
//****************************************************************************************


bool resizeBuff(int numBytes,uint8_t** buff) {

if(*buff) { // If we did NOT get passed in a NULL..
free(*buff); // We free the memory.
*buff = NULL; // Set the pointer to NULL.
}
if (numBytes>0) { // If we got a positive non zero value..
*buff = (uint8_t*)malloc(numBytes); // We attempt allocate that number of bytes.
return *buff != NULL; // And we return true for non NULL result (non-NULL = Success)
}
return true; // In this case we were not asked to allocate anything so it was a success.
}

bool resizeBuff(int numBytes,char** buff) { return resizeBuff(numBytes,(uint8_t**)buff); }

bool resizeBuff(int numBytes,void** buff) { return resizeBuff(numBytes,(uint8_t**)buff); }

bool resizeBuff(int numBytes,float** buff) { return resizeBuff(numBytes,(uint8_t**)buff); }
Dimolade
DimoladeOP7d ago
Oh thats pretty cool
jim lee
jim lee7d ago
well thank you! It's actually in the LC_baseTools library. You can instal it from the library manager.
Dimolade
DimoladeOP7d ago
:arduinoheart:

Did you find this page helpful?