Wemos D1 char allocation problem

Hello…
I have trouble with char allocation. I want to read file from SPIFFS to char buffer. When I allocate buffer outside of function everything is ok. But if I try to allocate bufer inside function (local variable) device crashes. The sample routine does only load file…

Working one:

char myB[25000]; //actual file is around 20000bytes

int serverResp1(char* fname){
  File f = SPIFFS.open(fname, "r");
  if (f){
    filesize = f.size();                  
    int bytesRead = f.readBytes((char *)myB,filesize);
  }
  f.close(); 
  return filesize;
}

And crashing one:

int serverResp1(char* fname){
  File f = SPIFFS.open(fname, "r");
  if (f){
    filesize = f.size();                  
    char myB[filesize+1];
    int bytesRead = f.readBytes((char *)myB,filesize);
  }
  f.close(); 
  return filesize;
}

The locally myB array will be created on the stack so will be unavailable after the function returns

If all you are going to return is filesize what is the purpose of the myB array and the bytesRead variables ? In any case, as filesize is not declared in the function where is it declared ?

This is stripped down function. In real one the data is used. But this minimal one shows abnormal behaviour.

Please at least post a full sketch that compiles and demonstrates the problem. Without that we have no idea where an how variables are declared

Ok here is simplified code (doesn’t really use the data) but can be compiled. The target is wemos D1. on SPIFSS there should be text file named index.html. I do upload with arduino IDE.

In code there are “char myB” declaration in 3 places. Uncomment just one. Only the 1st one will work. But best way should be last one declaring real amount needed and not to use some magic number as sizes.

#include "FS.h"
  
char myB[5000];                       //This allocation works 
int serverResp1(char* fname){
  int filesize;
  //char myB[5000];                   //This allocation crashes the system
  File f = SPIFFS.open(fname, "r");
  if (f){
    //filesize = f.size();                  
    char myB[filesize];               //This allocation crashes the system
    int bytesRead = f.readBytes((char *)myB,filesize);
  }
  f.close(); 
  return filesize;
}


void setup() {
  Serial.begin(115200); 
  delay(1000);
  if(!SPIFFS.begin()){
    Serial.println("An Error has occurred while mounting SPIFFS");
  }
}

void loop(){
  Serial.println(serverResp1("/index.html"));
  delay(2000);
}

It works with myB declared globally because it is available throughout the sketch, whereas declaring it anywhere else can cause a problem because of the scope of the variable. Even worse would be to declare it more than once in different scopes so that you will never be certain which version is being used

If you want to declare myB based on the size of the file being read and use it outside of the scope in which it was declared then you need to pass it to any function that is going to use it

Having said that, in you example program that is not necessary if you declare myB inside the if(f) code because it is not used anywhere else.

I cannot test this with an ES8266 as I don’t have one to hand, but I have tested your code on an ESP32 and it works with myB declared just once in the if(f) code block, or at least it does once I uncommented filesize = f.size(); :slight_smile:

Hello,

I think 5kB is too much to be stored on the stack, so you may need to use malloc instead

I just try to avoid malloc and Strings as I got heap fragmentation problem.

Actually the buffer is used just in that function. I need to load page into string and do some data modification in string and finally send it. I know the scope of myB.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.