SOLVED: releasing memory in sub-function

Hi, I'm doing a program who get a line from the SD and shows it, this function is called getData()

String getDataSD(){

  memset(inputString, 0, sizeof(inputString));
  myFile = SD.open(getFileNameSD());
  //cursorPosition = getIndexFileSD("INDX");
  myFile.seek(cursorPosition);

  if(myFile){

    endOfLine = false;    

    while(myFile.available() && endOfLine == false){
      inputChar = myFile.read();
      
      if(inputChar == '*'){
        while(inputChar != '\n'){
          inputChar = myFile.read();
        }
      }else{
        cursorPosition = myFile.position()-1;
        //saveIndexFileSD(cursorPosition,"INDX");

        if(inputChar == 10 || inputChar == ' ') inputChar = myFile.read();

        while(inputChar != '\n'){
          if(stringIndex < 25){          
            inputString[stringIndex] = inputChar;
            stringIndex++;
            inputChar = myFile.read();
          }
        }
        inputString[stringIndex-1] = '\0';        
        stringIndex    = 0;
        endOfLine      = true;        
      }      
    }
    myFile.close();    
  }
  return inputString;
}

I don't have problem with this function. To get the name of the file, I've created another function who looks for it in a folder, this function is called getFileNameSD()

char* getFileNameSD (){

  char folder[] = "/ACC";

  myFile = SD.open(folder);
  myFile = myFile.openNextFile();
  
  if(!myFile) myFile.rewindDirectory();
  
  if(myFile){
    char fullPath[sizeof(folder)+ sizeof(myFile.name())];

    strcpy(fullPath,folder);
    strcat(fullPath,"/");
    strcat(fullPath,myFile.name());
    
    myFile.close();

    return fullPath;
  }
}

I'm having problem with this last function, it is not releasing or overwriting some data, so every time it's called, it is stored new data in memory

I've included the memory Free library to see where is the problem. When I call the getDataSD and write the file manually I dont have problem

myFile = SD.open("/ACC/11001");
freeMemory()=6592
/-27/-26/-56/
freeMemory()=6592
/-27/-26/-56/
freeMemory()=6592
/-27/-26/-56/
freeMemory()=6592
/-27/-26/-56/
freeMemory()=6592
/-27/-26/-56/
freeMemory()=6592
/-27/-26/-56/

the memory always is the same.

but not when I call the getFileNameSD()

myFile = SD.open(getFileNameSD());
freeMemory()=6571
/-27/-26/-56/
freeMemory()=6540
/-27/-26/-56/
freeMemory()=6509
/-27/-26/-56/
freeMemory()=6478
/-27/-26/-56/
freeMemory()=6447
/-27/-26/-56/
freeMemory()=6416
/-27/-26/-56/

I know I'm doing something wrong with getFileName() but I don't know what is, can anybody help/explain me?

FULL CODE:

#include <SD.h>
#include <MemoryFree.h>

File myFile;
int stringIndex = 0;
int cursorPosition = 0;
char inputString [25];
char inputChar;
boolean endOfLine;

void setup()
{
  Serial.begin(9600);

  Serial.print("Initializing SD card.");
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

}

void loop(){
  
  Serial.println(getDataSD());

  Serial.print("freeMemory()=");
  Serial.println(freeMemory());
}

String getDataSD(){

  memset(inputString, 0, sizeof(inputString));
  
  myFile = SD.open(getFileNameSD());
  myFile.seek(cursorPosition);

  if(myFile){

    endOfLine = false;    

    while(myFile.available() && endOfLine == false){
      inputChar = myFile.read();
      
      if(inputChar == '*'){
        while(inputChar != '\n'){
          inputChar = myFile.read();
        }
      }else{
        cursorPosition = myFile.position()-1;

        if(inputChar == 10 || inputChar == ' ') inputChar = myFile.read();

        while(inputChar != '\n'){
          if(stringIndex < 25){          
            inputString[stringIndex] = inputChar;
            stringIndex++;
            inputChar = myFile.read();
          }
        }
        inputString[stringIndex-1] = '\0';        
        stringIndex    = 0;
        endOfLine      = true;        
      }      
    }
    myFile.close();    
  }
  return inputString;
}

char* getFileNameSD (){

  char folder[] = "/ACC";

  myFile = SD.open(folder);
  myFile = myFile.openNextFile();
  
  if(!myFile) myFile.rewindDirectory();
  
  if(myFile){
    char fullPath[sizeof(folder)+ sizeof(myFile.name())];

    strcpy(fullPath,folder);
    strcat(fullPath,"/");
    strcat(fullPath,myFile.name());
    
    myFile.close();

    return fullPath;
  }
}

Could you maybe tidy up your post please?
Post full code, not snippets.

     char folder[] = "/ACC";
    char fullPath[sizeof(folder)+ sizeof(myFile.name())];

sizeof(folder) is 5 (four characters and a terminator).
sizeof(myFile.name()) is likely 2 (pointer to a character)

If the full path is longer than 6 characters this will overwrite the stack and cause a crash. The size of an array has to be a COMPILE TIME CONSTANT. You can't create an array variable with a size that changes.

If you know the maximum filename length, use that. Otherwise you have to get into some tricky memory allocation.

AWOL I added the full code in the first post.

Thanks for your help johnwasser

I changed that line to

char fullPath[10];

the actual file is called "11001", so folder 5 and file 5 is 10
I tryed that but is the same problem, and I have a doubt, the folder will be always the same name size, but the file can be 7 or 8 long (now I'm just testing with that name) so how coud I solve this?

no one can help me?

the actual file is called "11001", so folder 5 and file 5 is 10

Full path and file is "/ACC/11011"?

That's 10 plus terminator = 11 bytes.

Why don't you create a global variable to hold the data from the SD card. Then you know where it is and you can easily avoid overwriting it.

On the Arduino the concept of "releasing" memory is strange. There is no other program that could make use of it in the way that it could be reused on a PC.

...R

Hackscribble, you're right it's 11 but even changing that the problem continuing.

Robin2, actually I don't have problem holding the data from the SD I'm using a global var of type char who stores the information.

the problem is I want to get the name of the file automatically from a specific folder, there is where I'm having the problem at this moment. There is something wasting the memory when I request the name every time.

In getFileNameSD(), you use myFile to take the result of two file openings: first the folder, and then the file in the folder. You call close() only once, so maybe the open folder does not get cleaned up.

How about something like this - not tested! It use different local File objects for folder and file, and it closes both of them.

char* getFileNameSD ()
{
  char fullPath[20];
  char folder[] = "/ACC";
  File myDir = SD.open(folder);
  if (myDir)
  {
    File myFile = myDir.openNextFile();
    if(myFile)
    {
      strcpy(fullPath,folder);
      strcat(fullPath,"/");
      strcat(fullPath,myFile.name());
      myFile.close();
      myDir.close();
      return fullPath;  
    }
    else
    {
      // Handle file not found
      myDir.close();
    }
  }
  else
  {
    // Handle directory not opened
  }
}

gepd:
the problem is I want to get the name of the file automatically from a specific folder, there is where I'm having the problem at this moment. There is something wasting the memory when I request the name every time.

Well, what about allocating global variables to hold the file names?

Suppose you put every variable into a global variable - would that work?

...R

Hackscribble finally! you hit the head :smiley:

It solved my problem. I never saw it because I didn't thought the openNextFile() function like a new instance.
So I never closed it, even in the playground example don't do that, but now I noticed that has a description talking about a new instance.

Would be good if someone add this in the playground example.

Robin2 thanks for the advice, I changed the fullPath var to global, because someone told me I could be unsafe return the data in that way.

this is the final code:

#include <SD.h>
#include <MemoryFree.h>

File myFile;
int stringIndex = 0;
int cursorPosition = 0;
char inputString [25];
char inputChar;
boolean endOfLine;
char fullPath[11];

void setup(){

  Serial.begin(9600);

  Serial.print("Initializing SD card.");
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

}

void loop(){
  
  Serial.println(getDataSD());

  Serial.print("freeMemory()=");
  Serial.println(freeMemory());
}

void getDataSD(){

  memset(inputString, 0, sizeof(inputString));
  
  getFileNameSD();
  
  myFile = SD.open(fullPath);
  
  if(myFile){
    myFile.seek(cursorPosition);

    endOfLine = false;    

    while(myFile.available() && endOfLine == false){
      inputChar = myFile.read();
      
      if(inputChar == '*'){
        while(inputChar != '\n'){
          inputChar = myFile.read();
        }
      }else{
        cursorPosition = myFile.position()-1;

        if(inputChar == 10 || inputChar == ' ') inputChar = myFile.read();

        while(inputChar != '\n'){
          if(stringIndex < 25){          
            inputString[stringIndex] = inputChar;
            stringIndex++;
            inputChar = myFile.read();
          }
        }
        inputString[stringIndex-1] = '\0';        
        stringIndex    = 0;
        endOfLine      = true;        
      }      
    }
    myFile.close();    
  }
}

void getFileNameSD (){

  char folder[] = "/ACC";
  File myDir = SD.open(folder);
  
  memset(fullPath, 0, sizeof(fullPath));

  if (myDir){
    myFile = myDir.openNextFile();
    
    if(myFile){
      strcpy(fullPath,folder);
      strcat(fullPath,"/");
      strcat(fullPath,myFile.name());
      myFile.close();
      myDir.close();
    }else{
      // Handle file not found
      myDir.close();
      fullPath[0] = '0';
    }
  }else{
    // Handle directory not opened
    fullPath[0] = '0';
  }
}

Thanks to all who took the time and tried to help me.