problems reading SD card on Ethernet Shield

Hi guys. Im having problems to read files in a SD card, when I read them it stop to read after a while. Im using this function to read a file:

#include <SPI.h>
#include <SD.h>

void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}

Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);

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

}

void loop()
{
char* path = GetPath("22.INI");
String returnConf = ReadFile(path);
Serial.println(retornConf );
}

String ReadFile(String path){

String returnStr= "";
// Serial.println("ReadFile- Initializing" + path);

File file = SD.open(path, FILE_READ);

if(file){ // after a while this variable stop to return true
while(file.available()){
char temp = (char)file.read();
returnStr+= temp;
}
file.close();
return returnStr;
} else Serial.println("ReadFile- File not initialized !");
file.close();
return "";
}

Someone can help me plz

I don't think that code you posted will compile but, despite that, where does the code stop? What is the last message on the serial monitor?

thanks for aswer. Sorry about the code, some lines is wrong and a function is missing.

#include <SPI.h>
#include <SD.h>

void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}

Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);

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

}

void loop()
{
char* path = GetPath("22.INI");
String returnConf = ReadFile(path);
Serial.println(returnConf );
}

String ReadFile(String path){

String returnStr= "";
// Serial.println("ReadFile- Initializing" + path);

File file = SD.open(GetPath(path), FILE_READ);

if(file){ // after a while this variable stop to return true
while(file.available()){
char temp = (char)file.read();
returnStr+= temp;
}
file.close();
return returnStr;
} else Serial.println("ReadFile- File not initialized !");
file.close();
return "";
}

char* GetPath(String path){
int len = ((String)path).length();
char* chrFile = new char[len+1];
for(int x = 0 ; x < len ; x++){
chrFile[x] = path[x];
}
return chrFile;
}

but has no message only the Serial.print with "ReadFile- File not initialized !", but the loop() stop to running.

First, please put your code the the code tags.

I'll take a guess that you probably have a problem with the variables in GetPath going out of scope before you use them.

Sorry about the code, my first post here. I kinda figured what's wrong. Sounds like memory leak, I put free(path) in the end of loop() and work, but this is just a samples Im trying to do. My real code is attached in the post.

ps.: Cant find Code Tag.

WebServer.ino (8.46 KB)

char* GetPath(String path){
  
  int len = ((String)path).length();
  char* chrFile = new char[len+1];
  for(int x = 0 ; x < len ; x++){
    chrFile[x] = path[x];
  }  
  return chrFile;
}

The useless String class has a toCharArray() method that doesn't rely on dynamic memory allocation.

It isn't clear what you are trying to do, but your overuse of Strings on an Arduino with little memory doesn't make sense.

The code tag is the '#' button above the message box. Highlight your code and click that button.

The memory allocation for the variable chrFile in this function is released when the GetPath function returns. The function is returning a pointer to memory that has now been released. Don't do that. That memory will probably be overwritten by the next function call before you can access the previous value stored there. Either put the chrFile variable in the calling function or in global memory.

char* GetPath(String path){
  int len = ((String)path).length();
  char* chrFile = new char[len+1];

// other unreadable code here

  return chrFile;
}

BTW, I don't use the String data type. I have found it to be unreliable. I use all character arrays.

Thanks all for the answer. If I replace all String with char* I will lose all functions: lastIndexOf(), indexOf(), toInt()... or has a work around with char* ?

If I replace all String with char* I will lose all functions: lastIndexOf(), indexOf(), toInt()... or has a work around with char* ?

Of course you will not be able to use those methods. And, no, there is no "workaround".

There are alternate functions, but they are not workarounds, since there is no problem to be worked around.

Ok guys, thanks for the answer and I will post here if the changes of Strings to char* will work.

Hi im back again :(, now I have changed my code, I changed every String to char* but the loop continues frozen after a while.
code:

#include <SPI.h>
#include <SD.h>
#include <memory.h>


File root;

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output
  // or the SD library functions will not work.
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);

  if (!SD.begin()) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
 
 
 root = SD.open("/");

}

void loop()
{
  EnviaConfig(root);
}
int ChrIndexOf(char* str, char character){
  int pos = -1;
  for(int i = 0; i < strlen(str); i++)
  {
     if(str[i] == character)
     {
  		  pos = i;
  		  break;
     }
  }
  return pos;
}

char* subString(char* str, int index, int count){
    char *res = (char*)malloc(count + 1);
    if (res) {
        strncpy(res, str + index, count + 1);
    }
    return res;
}

char* LerArquivo(char* path){
  char* valor = new char[100];
  char* retorno;
  int tamanho = 0;
  File file = SD.open(path, FILE_READ);
  if(file){  
    while(file.available()){ 
      char temp = (char)file.read();             
      valor[tamanho] = temp;
      tamanho++; 
    }
    file.close();
    retorno = new char[tamanho];    
    strncpy(retorno, valor, tamanho);
    free(valor);
    return retorno;
  } else Serial.println("LerArquivo - Arquivo nao inicializado !");
  file.close();
  return "";
}



void EnviaConfig(File directory) {
  char* configs = new char[100];
  directory.rewindDirectory();
  while (true) {
    File entry = directory.openNextFile();
    if (!entry) {
      entry.close();
      break;
    }
    if (!entry.isDirectory()) {
      if (strcmp(".INI", entry.name()) == -4) {
        if (strcmp("FAIXA.INI", entry.name()) != 0) {
          int pino = 0, y = 0, tempInt = 0;
          char* retornoConfig = LerArquivo(entry.name());
          
          char* tempPino = new char[3];
          char* tempModo = new char[7];
          for (int i = 0 ; i < strlen(retornoConfig) ; i++) {
            if ((retornoConfig[i] != '=') && (y == 0)) {
              tempPino[tempInt] = retornoConfig[i];
              tempInt++;
            } else if (y == 1) {
              tempModo[tempInt] = retornoConfig[i];
              tempInt++;
            } else {
              y = 1;
              tempInt = 0;
              pino = atoi(tempPino);
            }
          }
          itoa(pino, (tempPino), 10);
          char* chrValor = new char[1];
          itoa(digitalRead(pino), chrValor, 10);
          strncat(configs, tempPino, strlen(tempPino));
          strncat(configs, "=", 1);
          strncat(configs, chrValor, strlen(chrValor));
          strncat(configs, "|", 1);
          free(chrValor);
          free(tempPino);
          free(tempModo);
          free(retornoConfig);
        }
      }
    }
    entry.close();
  }
  char* resultado = new char[strlen(configs)];
  resultado = subString(configs,0,strlen(configs));
  Serial.println(resultado);
  free(configs);
  free(resultado);
}

Can someone help me plz?

          char* chrValor = new char[1];

You expect to store a '0' or '1' in this array AND a NULL terminator? No, you won't.

Stop with all the dynamic memory allocation. You are just shooting yourself in the foot.

char* subString(char* str, int index, int count){
    char *res = (char*)malloc(count + 1);
    if (res) {
        strncpy(res, str + index, count + 1);
    }
    return res;
}

What does this function accomplish that strdup() doesn't? There is no need to reinvent all the string handling functions. Professional programmers have spent years making sure that the string function that come with the compiler work perfectly. Can you say the same? No, you can't, as evidenced above.

  char* valor = new char[100];

Now, this is just plain stupid. A static array would accomplish the same thing, with no dynamic memory allocation required.