0

For the below code snippet

const char* fr_fbdb(char tag[30]) // fn for retrieving data 
{
  char full_path[120]; 
  const char *_dt ; 
  strcpy(full_path , base_path);
  strcat(full_path , tag);
  Serial.print( "retrieving from " ); 
  Serial.println(full_path) ; 
  Firebase.get(firebaseData, full_path);
  _dt = firebaseData.cstrData();
//  Serial.print("while ext: "); 
//  Serial.println(_dt); 
  return _dt ; 
} 

void retreive_sch()
{
  int no_tag = strlen(*tag) ;
  //Serial.print("no. of tags in the DB: ");
  //Serial.println(no_tag);
  const char *_data[no_tag];


  Firebase.get(firebaseData, "/SCHEDULE DETAILS/SELECTED");
  sch_no = firebaseData.cstrData();

  Serial.print("extracting schedule");
  Serial.println(sch_no);

  strcat(base_path , sch_no); // base path w/ sch no.

  for (int i = 0 ; i < 6 ; i++) 
  {
    _data[i] = fr_fbdb(tag[i]); 
    Serial.print("while ext: "); 
    Serial.println(_data[i]);  
    
  }

  for(int i=0 ; i<6 ; i++)
  {
    Serial.print("after extraction:"); 
    Serial.println(_data[i]) ;
  }
}

This is the output:

retrieving  schedule changes -- setup 
extracting schedule3
retrieving from /SCHEDULE DETAILS/SCHEDULE3/DATE
while ext: [1609612200000,\"inf\"]
retrieving from /SCHEDULE DETAILS/SCHEDULE3/FREQ FR
while ext: \"-2\"
retrieving from /SCHEDULE DETAILS/SCHEDULE3/FREQ TO
while ext: \"-2\"
retrieving from /SCHEDULE DETAILS/SCHEDULE3/WEIGHT
while ext: 29
retrieving from /SCHEDULE DETAILS/SCHEDULE3/TIME
while ext: \"6:30\"
retrieving from /SCHEDULE DETAILS/SCHEDULE3/frequency
while ext: \"-1\"
after extraction:"root":[]
after extraction:\"-1\"
after extraction:keep-alive
after extraction:\"-1\"
after extraction:"root":[]
after extraction:\"-1\"

As you can see, the output of the same variable _data[] inside that particular function changes. Any idea why?

4
  • 3
    I would suggest you pick up a book about C++ and understand how to use const and what happen and the scope of a locally declare variable within a function.
    – hcheung
    Feb 9 at 4:11
  • _data is a global var & both set of print statements are within the same Fn. I hv used const char* fr_fbdb bcos firebaseData.cstrData() returns a c-string. Here's how I thought the flow was going to be: I call retrieve_sch() in the setup() . Then I get no. of tags from strlen(*tag) (tag holds strings such as DATE , WEIGHT, etc.). Then using a for loop that calls fr_fbdb() n no. of times get the req. tags. I also print the value that was retrieved here and in the for loop below. Pls point out where there might be flaws. Feb 10 at 10:27
  • _dt is a locally declared variable, its scope remain local and when a call is return from the function, whatever stored in the _dt could be free up and the memory could be override.
    – hcheung
    Feb 10 at 15:37
  • "_data" has the value that is returned by the function fr_fbdb() which is confirmed by the print statements in the 1st for loop of retreive_sch() . In the second for loop of retreive_sch() the same var, _data gives different values. My claim is, if there was a pblm (bcos of scope of variables), then it should have been shown in the first print statement. (In case you haven't noticed, I've commented the print statements in fr_fbdb()) Feb 11 at 1:56
1

The problem is these lines of code in your function fr_fddb():

  Firebase.get(firebaseData, full_path);
  _dt = firebaseData.cstrData();

You didn't share enough code to make this clear, but firebaseData appears to be a global which you reuse. When you call its .cstrData() method you're getting a pointer to the same buffer each time, and that buffer is overwritten each time you call Firebase.get().

You can verify this by printing the pointer value each time through, like so in your retrieve_sch() function:

  for (int i = 0 ; i < 6 ; i++) 
  {
    _data[i] = fr_fbdb(tag[i]); 
    Serial.print("while ext: "); 
    Serial.println(_data[i]);  
    Serial.printf("_data[i] pointer %p\n", _data[i]);
  }

You'll likely see that the 6 pointers are identical. The value is changing because you keep reusing the same string.

The easy fix is:

  Firebase.get(firebaseData, full_path);
  _dt = strdup(firebaseData.cstrData());

This allocates memory and stores in it a duplicate of the string that was fetched from Firebase. Your function will now return that and firebaseData can safely be reused.

This solution will require you to free that memory at some point when you're doing using it by calling free(_dt); or whatever you're holding the pointer in when you're done. I leave that as an exercise for you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.