Issue with depth of functions

So i have strange issue.
I have a bit large project so i am not posting full code (only function in question) as it will be huge (4k lines of code)

bool writeToFile(char *fileName, char *messageIn, unsigned int msgLength, bool debug, char *source, int sourcelength) {
  source[sourcelength + 0] = '>';
  source[sourcelength + 1] = '>';
  source[sourcelength + 2] = 'w';
  source[sourcelength + 3] = 'r';
  source[sourcelength + 4] = 'i';
  source[sourcelength + 5] = 't';
  source[sourcelength + 6] = 'e';
  source[sourcelength + 7] = 'T';
  source[sourcelength + 8] = 'o';
  source[sourcelength + 9] = 'F';
  source[sourcelength + 10] = 'i';
  source[sourcelength + 11] = 'l';
  source[sourcelength + 12] = 'e';
  source[sourcelength + 13] = '(';
  source[sourcelength + 14] = ')';
  source[sourcelength + 15] = 0;
  if (debug) {
    Serial.println(source);
  }
  if (SD.exists(fileName)) {
    Serial.println(F("delete if exists"));
    SD.remove(fileName);
  }
  if (debug) {
    Serial.println(F("create file"));
    Serial.println(fileName);
  }
  File myFileA = SD.open(fileName, FILE_WRITE);
  if (debug) Serial.println(F("write to the file"));
  if (myFileA) {
    if (debug) Serial.println(F("file created and open"));
    int i = 0;
    while (i < msgLength) {
      Serial.println("write 256");
      Serial.println(myFileA.write(messageIn + i, min(256, msgLength - i)));
      myFileA.flush();
      i += 256;
    }
    myFileA.close();
  } else {
    source[sourcelength] = 0;
    return false;
  }

  source[sourcelength] = 0;
  return true;
}

I am using arduino due (monitoring memory etc. so i know i am not hitting memory limits, at least i do not see other issues as all other memory issues i am addressing ).
i hit the wall with following issue.
I have a function that is designed to write file passed as parameter (almost all parameters in my code are references so i do not increase memory usage) with error handling etc

Depends on the depth of function calls the SD.exists and all related functions , open, etc will work or fail.
i.e. if i call this function from level 3 i.e. func1->func2->writeToFile->SD.exists it will work
however if i call another function in between i.e. func1->func2->functExtra->writeToFile->SD.exists it will not work.

Anyone has link to some documentation about memory management why this could happen.
As work around i can encapsulate code into function above and make copy of that somewhere else but this is not good practice

here are libraries that i have included in the project

#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <TimeLib.h>
#include <SD.h>
#include <Ethernet.h>
#include <Scheduler.h>

Then please post an MRE.
https://forum.arduino.cc/t/how-to-get-the-best-out-of-this-forum/679966

" The forum has a limit of 120000 characters per post, which means that you can't post a program longer than this directly. In this case, you can attach the .ino file to your post or, if you are using Arduino Create, you can post a link to your project.

However, consider that the longer your program, the harder it is for anyone to understand it and help you. For this reason, consider writing a short program that illustrates the problem and post or link to that instead. You are more likely to get help with a short, easy to understand program than with a long, complicated one. For more about this see How to create a Minimal, Reproducible Example ."

What about using strcpy() or strncpy()?

EDIT
I'd not so much suspect the depth of nesting of the function calls, more than some parameter to writeToFile() has lost its value somewhere in the call chain.
Also, just going by the names you have used here: source[sourcelength + 15] = 0; are you sure that there is enough room at the end of source[] for all that ? I guess the longer the call chain, the bigger sourcelength gets.

1 Like

how do you know the code is not writing past the length of source?

This is for debug. That part is ok as I can see in serial info which function was called.
Setting 1 character at the time was to avoid strings.
The way I recognize it is failing on SD.exists was by putting file name and run it with that extra code and it failed. When I take copy paste to function that is calling this it will work. I suspect it is something with Ethernet/se shield. Maybe callback is failing

Are you getting payed by the LOC? :astonished:

I'd love to know your justification.

1 Like

How big is the character array source[] ? What is the value of sourcelength, including the room for the extra characters you've squeezed in at the end, when the failure occurs ? Clearly, you are maintaining a representation of the call chain in source[] and that will get larger as the function nesting gets deeper which does sound like a plausible explanation for your problem.

You could do something like this:

  strcpy( source[sourcelength], ">>writeToFile()" ) ;

to avoid the laborious 1 character at a time initialisation.

Better still, strcpy_P (assuming AVR)

? ? ?
This does not appear to work as it looks like it should. Back to the drawing board.

Did you miss one of these '&'?

Or maybe

strcpy( source + sourcelength, ">>writeToFile()" ) ;

I'be just been (re)reading Chapter 5 in the bible.

a7

and this alternative appears OK:

void setup() {
  Serial.begin(115200);
  Serial.println( "hello world" );
  char source[80] = "012345678901234567890123456789012345678901234567890123456789";
  strcpy( (&source[0] + 10) , ">>writeToFile()") ;
  Serial.println( source );
}

void loop() {
  // put your main code here, to run repeatedly:

}

I left source 0 filled and tried to add something in the middle. Of course the first 0 ended the printing. Stupid error.

Or even let the processor do the hard sums, and just use strcat/strcat_P

strcpy() will bring the null terminator into the destination string, so what you added will be at the end.

So maybe strncpy() to put something in the middle of something else if that was part of what needed to be done.

a7

Based on this, the OP seemed to like the terminating null. I presume he decremented the value passed to his variable stringlength before calling his function writeToFile() which would effectively concatenate something onto the end of it.

Afaik based on memory monitoring.
Actually strcpy indicates that you are using string. So it will create temp string. If you do like above it will not initialize string as it is char each time.
Before I had issue with strings so I have decided to absolutely avoid it at all cost :wink:

You are confused. Do you perhaps mean the Arduino "String" class (note the capital 'S')?

1 Like

No, it definitely will not

For your reference..
Null-terminated byte strings

all good.. ~q

The only string that will be created (by the compiler, at compile time) is ">>writeToFile()". That's only 16 bytes. That string can be copied to your string with a call to strcpy() (as others have pointed out already). That's 16 bytes plus a small amount of machine code to call strcpy() (a handful of bytes). You're looking at maybe a couple dozen bytes total.

How many bytes of machine code does your code produce? A lot more than that for sure (a rough estimate is 3 bytes, at a minimum, for each character added to the array, or 48 bytes of machine code; more likely it's several bytes per character, or more than 100 bytes total).

I'll take a couple dozen bytes over more than 100 bytes, unless speed is critical (which it's not unless you can show that it is).