variables within an object are varying

Hi,
there is a problem I cannot understand:
The content of variables is different if I take it from within a method of a class or from outside.
The code is for testing with Teensy3.2 and with Arduino Mega2560.
The test results shown here come from Mega2560.

Short explanation of code problem:
There is a class SdPlayClassTe containing a method setFile() which opens a file and defines some file parameters

typedef struct {
	uint8_t     Attributes;
	uint32_t    Size;           // in bytes
	uint32_t    FirstCluster;   // First cluster
    
	uint32_t    ActSector;      // 0 to (SD_L2_FAT.SecPerClus - 1)
	uint32_t    ActBytePos;     // 0 to Size
} SD_L2_File_t;

Additionally it computes two public variables, start_sec_file and anzsect, from these parameters, see code part of audio.cpp.
The content of parameters Size and ActSector and variable anzsect is different when printing them inside setFile() or after calling setFile() and printing them outside.

The output from running the sketch und IDE 1.8.4:

SDcardTest
Wiring is correct and a SD-card is present.
Looking for ANSAGEK5.AHM... 
 in setFile(), fileinfo.ActSector|fileinfo.Size: 22336|3002544
22336 5865
found. fstat=2
 in setup(), Fileparameter from fileinfo:
Attributes=32, Size=53424, FirstCluster=45, ActSector=95, ActBytePos=0
abgeleitete Parameter:
start_sec_file=22336, anzsect=0
...

The value of anzsect is correct (=5865) inside setFile() but wrong outside (=0).
The values of file parameters ActSector and Size are correct (=22336, =3002544) inside setFile() but wrong (=95, =53424) outside!

The code of the sketch and the method setFile() is included here. The complete class definition and implementation is in the attachment. The library is not attached because it was not possible to mark all the files and attach them additionally. I will post a reply with the library attached too.

#include "audio.h"

#include "sd_l2_Te.h"

#define SMS_LEN         160
#define TALK_BUFF_LEN   1024

byte talk_buff[TALK_BUFF_LEN];  // Daten zur Wiedergabe der Sprache
char msgtxt[SMS_LEN]; 
uint8_t   fstat;

void setup() {
  uint32_t read_time;
  int16_t anz_errors;
  // put your setup code here, to run once:

  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println(F("SDcardTest"));
  
  // SD-card aktivieren:
  SdPlay.setWorkBuffer(talk_buff, TALK_BUFF_LEN);
  SdPlay.setSDCSPin(4); 
  if (!SdPlay.init()) {
    sprintf(msgtxt,"Error code: %d, --> runup stopped", SdPlay.getLastError());
      Serial.print(F("SD-card initialization failed: runup stopped, "));
      Serial.println(msgtxt);

    while(1);
  } 
  else {
      Serial.println(F("Wiring is correct and a SD-card is present.")); 
  }

// the problem is in the following part of code ...------------------------------------------------
  Serial.print(F("Looking for ANSAGEK5.AHM... "));
  fstat=SdPlay.setFile((char*)("ANSAGEK5.AHM"));  // ohne type casting ergibt das "warning"
  if(fstat<2) {
    sprintf(msgtxt,"Error code: %d, --> runup stopped", SdPlay.getLastError());
    if (fstat==1) Serial.println(F("file is fragmented!"));
    else Serial.println(F(" not found on card!"));
    Serial.println(msgtxt);
  
    while(1);
  } 
  else {
    Serial.print(F("found. fstat="));Serial.println(fstat);

    Serial.println(F(" in setup(), Fileparameter from fileinfo:"));
    sprintf(msgtxt,"Attributes=%d, Size=%u, FirstCluster=%u, ActSector=%u, ActBytePos=%u",
                  SdPlay.fileinfo.Attributes,
                  SdPlay.fileinfo.Size,
                  SdPlay.fileinfo.FirstCluster,
                  SdPlay.fileinfo.ActSector,
                  SdPlay.fileinfo.ActBytePos);
    Serial.println(msgtxt);
    Serial.println(F("abgeleitete Parameter:"));
    sprintf(msgtxt,"start_sec_file=%u, anzsect=%u",
                  SdPlay.start_sec_file, SdPlay.anzsect);
    Serial.println(msgtxt);
  }
// ... up to here ----------------------------------------------------------------------------------
  // now testing SD card:
  read_time=SdPlay.speed_test(&anz_errors);
  Serial.print(F("Lesedauer in usec: "));Serial.println(read_time);
  Serial.print(F("Anzahl Fehler dabei: "));Serial.println(anz_errors);
}

void loop() {

}

The class implementation, audio.cpp, only code of setFile(), complete in the attachment:

...

// ************* Instantiations ********************
SdPlayClassTe SdPlay;

// ************* Class implementation **************

...
/**
 * Sets file to play.
 *
 * \return 
 *  0   file not found
 *  1   file found, but fragmented
 *  2   file ok
 *  (fetch error-code using getLastError)
 */
uint8_t SdPlayClassTe::setFile(char *fileName) {
  if(!_pBuf) {
    _lastError = SSDA_ERROR_NOT_INIT;
    return(false);
  }
  uint8_t retval;

  fileinfo.Size = 0;
  retval = SD_L2_SearchFile((uint8_t *)fileName, 0UL, 0x00, 0x18, &fileinfo);
  
  if(retval>0) {
     _lastError = retval;
     retval=0;
  } 
  else {  // file found
    start_sec_file = fileinfo.ActSector;
    anzsect = (fileinfo.Size + 511)/512;
    retval = 2;

// extra prints for testing:
    Serial.print(F("\n in setFile(), fileinfo.ActSector|fileinfo.Size: "));
    Serial.print(fileinfo.ActSector);Serial.print("|");Serial.println(fileinfo.Size);
    Serial.print(start_sec_file);Serial.print(" ");Serial.println(anzsect);

    if (SD_L2_IsFileFragmented(&fileinfo)) retval=1;
  }

  return(retval);
}

...

audio.cpp (4.1 KB)

audio.h (2.66 KB)

here is the library for those who need it.

sd_l0_Te.cpp (4.25 KB)

sd_l0_Te.h (2.83 KB)

sd_l1_Te.cpp (17 KB)

sd_l1_Te.h (3.77 KB)

sd_l2_Te.cpp (16.3 KB)

sd_l2_Te.h (2.68 KB)

You are printing the values two different ways. In one case, you let Serial.print() decide how to print the value in SdPlay.fileinfo.ActSector. Since ActSector is a uint32_t, or unsigned long, Serial.print() prints the value as an unsigned long.

In the other case, you are using sprintf() to convert the value to a string. But, you are using the %u format specifier, which is NOT the correct specifier for longs. %ul is.

ok,

after changing all %u to %lu, now it is correct, thank you,

But this is a hot topic. With %u there is no error and no warning during compilation inspite of huge errors at run time.

SupArdu

But this is a hot topic. With %u there is no error and no warning during compilation inspite of huge errors at run time.

Well, C does allow you to shoot yourself in the foot. Hope your toes all heal.

SupArdu:
But this is a hot topic. With %u there is no error and no warning during compilation inspite of huge errors at run time.

The C compiler does not parse and verify the arguments that you pass to functions - to do that, it would have to have detailed knowlege of how each function works. It's our job as programmers to know what the functions that we invoke do.