sprintf kills my program

hi,
a very mysterious effect makes me troubles.
For debugging I inserted an sprintf() statement in my sketch, reusing a string which is available for that purpose. The relevant parts of my sketch:

...
#define SMS_LEN         160
word wmean, wmin, wmax;
byte wdir;
byte pos_sms_rx;
...
char  msgtxt[SMS_LEN];
...
Serial.println(F("----> Daten an Server"));Serial.flush();
t_gprs=millis();
wdir = getServerData(19, 19, &wmean, &wmin, &wmax, &pos_sms_rx);
sprintf(msgtxt,"wmean=%d wmin=%d wmax=%d vardir=%d wdir=%d", 
                    wmean, wmin, wmax, pos_sms_rx, wdir); 
Serial.print(msgtxt);Serial.flush();
...

The output of the sketch is

----> Daten an Server
wmean=2708 wmin=0 wmax=21024 vardir=0 wdir=9OK/Programm: VoiceSMSClientDisplay.ino

From the output the part "K/" I dont know the origin.
But the part "Programm: VoiceSMSClientDisplay.ino" is an output from the setup() function of the sketch, i.e. a reset has occurred.

After commenting the two lines with the sprintf() statement the program continues as it should do.
The length of the string within msgtxt[] is much less than the maximum possible 160 characters.

What could be the reason of reseting my sketch?

Just for fun I inserted the two statements

sprintf(msgtxt,"wmean=%d wmin=%d wmax=%d vardir=%d wdir=%d",
                    wmean, wmin, wmax, pos_sms_rx, wdir);
Serial.print(msgtxt);Serial.flush();

at different locations within my sketch.

Within setup() it works without reset.
Within loop(), reset occurs when the statements are inserted at different locations.

What is going on here?

SupArdu

It's going to be very useful to show the entire program rather than a snippet.

The whole sketch is quite large. It is a GSM application checking phone calls and SMS, reading wind data from a wind sensor via HW Serial (RFrec) and sending some data to a server.
Here is the final part of loop():

#define SMS_LEN         160
word wmean, wmin, wmax;
byte wdir;
byte pos_sms_rx;
...
char  msgtxt[SMS_LEN];
...
setup() {
...
}

loop() {
// the first part of loop() contains checking if a phone call came in and if an SMS was received.
...
// check if Winddata are available:
  wanz=0;
  while (RFrec.available()) {  // Daten sind angekommen, evtl. bereits mehrere
    // WxxxRxx<CR> oder TxxxxHxx<CR>

    newdat=true;
    
    c=RFrec.read(); Serial.print(c);
    msgtxt[wanz++]=c;
    while (c > 31) {    // immer (nur) einen ganzen Datensatz einlesen
      if (RFrec.available()) {
        c=RFrec.read();
        msgtxt[wanz++]=c;
//        Serial.print(c);
      }
    }
    msgtxt[wanz]=0;   // String abschliessen

    // Message interpretieren:
    if (msgtxt[0] == 'W') { // Winddaten in Ringpuffer legen
      wmean=atoi(&(msgtxt[1]));
      wdir=atoi(&(msgtxt[5]));
      storeWDat(wmean, wdir);   // store data in a ring buffer, schaltet rbuf_idx weiter

      dispWindData();    // display data on epd-display
    }
    else {
      if (msgtxt[0] == 'T') { // Temperaturdaten abspeichern
        temp_act=atoi(&(msgtxt[1]));
        rh_act=atoi(&(msgtxt[6]));
      }
      else Serial.println(F("unbekannte Daten vom Funkempfaenger!!"));
    }
    wanz=0;
  } // while (RFrec.available())
  
  if (newdat) epd_update();
  newdat=false;

  // check if data shall be sent to server:
  if ((millis()-t_gprs) > 300000) { // alle 5 Minuten
//    Serial.print(millis());
    if (SerMonitor)
      Serial.println(F("----> Daten an Server"));Serial.flush();
    t_gprs=millis();
    // 5 Minuten enstspr. ca. 19 Messdaten
    wdir = getServerData(19, 19, &wmean, &wmin, &wmax, &pos_sms_rx);  // die letzten 19

    sprintf(msgtxt,"wmean=%d wmin=%d wmax=%d vardir=%d wdir=%d",   // here is the problem ..
                    wmean, wmin, wmax, pos_sms_rx, wdir);   //.. causing the reset!!!
                      // deactivating/commenting the sprintf() statement results in perfect operation
    Serial.print(msgtxt);Serial.flush();

    stat = inet.setupGPRSConnection();
    if (stat < AT_RESP_OK) {  // -1, 0, 1, noch ein Versuch
        inet.closeBearer();
        delay(100);
        gsm.InitParam(PARAM_SET_0);
        delay(100);
        gsm.CheckRegistration(); // hier wird auch PARAM_SET_1 aktiviert
        delay(100);
        stat = inet.setupGPRSConnection();
    }
    if (stat == AT_RESP_OK) {
      delay(100);
      if (inet.sendHTTPdata(wmean, wmin, wmax, wdir, temp_act, rh_act) == 1) {
        delay(100);
        rsp=inet.closeBearer();
        if (SerMonitor) {
          Serial.print(F("link closed with "));
          Serial.println(rsp);
        }
        msg_cnt++;
      }
      else {
        if (SerMonitor) Serial.println(F("sendHTTPdata() failed"));
        fail_cnt++;
      }
    }
    else {
      if (SerMonitor) Serial.println(F("setupGPRSConnection() failed"));
      fail_cnt++;
    }

    Serial.print(F("OK/fail: "));Serial.print(msg_cnt);
    Serial.print("/");Serial.println(fail_cnt);
  }
}   // loop

Is this code sufficient?

SupArdu

The whole sketch is quite large

Alarm bells.

The code is large for posting. But the code runs on an Arduino Mega2560 which has sufficient flash and RAM:

Sketch uses 26,700 bytes (10%) of program storage space. Maximum is 253,952 bytes.
Global variables use 4,387 bytes (53%) of dynamic memory, leaving 3,805 bytes for local variables.

I just made a further test, replacing the sprintf() by Serial.print()'s:
I replaced

sprintf(msgtxt,"wmean=%d wmin=%d wmax=%d vardir=%d wdir=%d", 
                    wmean, wmin, wmax, pos_sms_rx, wdir); 
    Serial.print(msgtxt);Serial.flush();

by the following code:

Serial.print(F("wmean="));Serial.print(wmean); 
    Serial.print(F(" wmin="));Serial.print(wmin);
    Serial.print(F(" wmax="));Serial.print(wmax);
    Serial.print(F(" vardir="));Serial.print(pos_sms_rx);
    Serial.print(F(" wdir="));Serial.println(wdir);

and it works!!

You're more than likely having memory issues. Any variable that is not declared globally will add to memory usage at occasion, nested function calls will add, recursive functions are a nearly certain death unless you know what your doing and so on.

Post or attach your complete code.

well, lack of RAM is what I suspected too. On the other hand a lot of RAM is available.

The whole program really is a lot because there are some libraries included. And I don't expect you or somebody else to analyze all the code.

Now I will check where it is possible to reduce RAM usage.

Thank you all for your tips.

SupArdu

SupArdu:
well, lack of RAM is what I suspected too. On the other hand a lot of RAM is available.

Are you taking about flash memory or SRAM. I usually run out of SRAM long before I run out of flash memory. I've had situations where the compiler tells me I've only used 70% of SRAM and only 50% of flash, but the program crashed. The reason is because SRAM stores all of the data. Your F macro prevents duplicating strings and can help, but may not save the day. Don't forget that the figures given after a compile are static numbers. When the program runs, data are pushed and popped as functions come and go...the stack ebbs and flows. I ebbed and flowed right out of a Nano and into a Mega 2560.

could be you're blowing the stack.
try making msgtext[] static.

Something in your code is stomping over memory that doesn't belong to it.

The part of the sketch that you have shown us seems to be working perfectly fine. You build and print "wmean=2708 wmin=0 wmax=21024 vardir=0 wdir=9O" and it gets printed just great.

Obviously, something is printing "K/Program" (etc). What might that be? How could I possibly know? I'd have to pepper your code with log statements to work out what is going in. (TIP: check out the C++ FILE and LINE preprocessor macro.)

If the problem is as you describe it, then you are looking at many, many long and fruitless hours chasing down the errant line of code that writes one byte past the end.

If you are using many, many libraries that you found lying unmaintained in github repos, then you may never find the errant line of code.

It could be something obvious with one line of code.

It could be something that you are doing everywhere, and you need to rework all your code.

Or maybe the reason it blows up after that particular printf is that you lean over to your monitor to read it, and your chair leg is on top of the power supply cable to the aduino.

I've seen sprintf() collapse with too many substitutions, and simply broke it into multiple lines...

int x = sprintf(buf, "format  % % %", var, var, var);
sprintf(buf + x, "more... % % %", var, var, var);

I suspect the earlier comment about stack is involved, so the above is neat and easy.
Haven't seen it for a while.