Arduino with SD Card Memory Leak

Go To Last Post
22 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would like listing files on Arduino with SD card.

 

#include <MemoryFree.h>
#include <SD.h>

String current_directory;
File directory;
File filesystem_member;

void list_files(void)
{
  Serial.print("Directory: ");
  Serial.print(current_directory);

  while (filesystem_member = directory.openNextFile())
  {
    Serial.write('\n');
    Serial.print(filesystem_member.name());

    if (!filesystem_member.isDirectory())
    {
      Serial.write('\t');
      Serial.print(filesystem_member.size());
      Serial.print(F(" byte"));
      Serial.write('\n');
    }

    filesystem_member.close();
  }

  filesystem_member.close();

  directory.rewindDirectory();
}

void setup()
{
  Serial.begin(9600);
  SD.begin();
  list_files();
  Serial.println(freeMemory());
  directory = SD.open("/");
}

void_loop()
{
  list_files();
  Serial.println(freeMemory());
  delay(2000);
}

But, the code has memory leak problem. Free memory are decreasing.

 

Has Arduino a bug?

 

Thanks for replies.

Last Edited: Tue. Mar 20, 2018 - 07:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe because there are two filesystem_member.close() statements?

Last Edited: Tue. Mar 20, 2018 - 03:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No. I tried it just.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have you asked on the actual Arduino forums?

 

If you do cross-post the same question in multiple places, always gives links between them.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Your usage seems quite different to this example:

 

https://www.arduino.cc/en/Refere...

 

In this they do the SD.begin() but then they use root = SD.open("/") (where "root" is a File) then root is used as the "input" to .openNextFile(). You have no apparent connection between the SD instance and the file operations then performed?

 

BTW the code you posted clearly isn't the code you are using:

String currnet_directory;
  Serial.print(current_directory);

So "current_directory" will be an unknown symbol. It's also curious that nothing in the code ever seems to set that String anyway ?? Neither initialize it nor update it.

 

The key thing in the example from the manual is probably not only that root = SD.open("stuff") but it ends:

  root.close();

Your equivalent of "root" is "directory". As I say I see you directory.openNextFile() (even though no connection to SD means it presumably just takes some default?) but you never appear to do directory.close(). I don't think directory.rewindDirectory() implies the same thing at all.

 

Oh and by the way I tried a google for "arduino sd file memory leak" and there's quite a number of threads on the Arduino forum about it but almost all seem to boil down to wrong usage. (I figured that if there really were a bug in a core bit of Arduino at least 50 others would have hit it/reported it before you got there!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I updated my code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I updated my code.

NEVER DO THAT!!!

 

It makes it impossible to follow the flow of the thread.  Instead, make a new post with the changes.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

I updated my code.

joeymorin wrote:
NEVER DO THAT!!!

+999

 

It makes it impossible to follow the flow of the thread. 

Indeed!

 

Instead, make a new post with the changes.

Just to be absolutely clear, that means that you should add a reply in this thread - not start a new thread!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's still wrong anyway - I don't see the directory being closed after open.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is this FatFS? I've never used fatfs myself, but as far as I know it can only handle one open file at any time, because it os optimizxed for space and only has one buffer for data.

A file has to be closed first before another can be opened.

 

My best/first guess is to compile this project on a PC and simulate the uSD card / routines.

(There probably already is some plugin for this from the fatfs development team).

Then step through the code to find your leak.

 

This may also be easily done with an Amel ICE, but I do not have that.

 

What are the contents of the leaked memory?

If you dump all ram to the serial port, does that give hints of the origin of the leak?

 

Does your file system use malloc() / free() combination? They should always be matched.

(And are generally advised against using them at all for small uC's, but uC's are getting bigger...).

Still, I probably prefer static memory allocation.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Paulvdh wrote:
Is this FatFS?
Nope, these are the "SD" and "File" classes in Arduino.

 

Source is here:

 

https://github.com/arduino-libra...

 

The (c) seems to suggest it was developed by Sparkfun

 

As it's implemented in C++ I rather imagine that by instantiating more than one object you can have more than one thing open at a time as everything is in classes rather than relying on anything global.

 

It's interesting to read the code to see that, for example, it's doing malloc() in the c'tor for File. The matching free() appears to be in the File::close() method. I don't see anything in SD.cpp doing malloc()s though.

 

Obviously one could pepper this code with Serial.println()s to note when things were being malloc()d or free()d to spot any inbalance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
one could pepper this code with Serial.println()s to note when things were being malloc()d or free()d to spot any inbalance.

Doesn't GCC have a feature to do that automatically - rather than do the peppering manually ... ?

 

something to do with "wrappers" ... ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yup, a thread about that in the last two weeks - as usual Georg-Johan had the skinny on how to do it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
(I figured that if there really were a bug in a core bit of Arduino at least 50 others would have hit it/reported it before you got there!)

 

I agree.

 

Which environment use am I instead of Arduino?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ercanersoy wrote:
Which environment use am I instead of Arduino?

Sorry,  I think that got lost in translation. What are you asking?

 

I think the point so far is that the problem is in your code, not in Arduino.

 

So the answer is to fix your code - not switch to another environment.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for my mistake.

 

Which environment use I instead of Arduino?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Well you can just write plain C (or C++ if you prefer) in Atmel Studio 7 and then that would let you use "FatFs" as the library for SD/MMC work.

But as others have said I am firmly convinced that there isn't a bug in the Arduino code and all this is simply an error in your use of the functions - I don't think you are balancing opens/closes so when the Arduino library does malloc()s it is not doing matching free()s to balance things because you simply aren't calling the right functions.

I already explained where to look at the code for the File/SD classes. You must have a copy locally - just modify that so that it uses Serial.println() to say when malloc()s and free()s are being called and you will see where it is you are doing malloc()s without free()s

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ercanersoy wrote:
Which environment use I instead of Arduino?

Sorry,  that's no clearer.

 

I think the point so far is that the problem is in your code, not in Arduino.

 

So the answer is to fix your code - not switch to another environment.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for replies. I changed my code that is given below. This code hasn't  memory leak problem.

#include <MemoryFree.h>
#include <SD.h>

File directory;
File filesystem_member;

void list_files(void)
{
  while (filesystem_member = directory.openNextFile())
  {
    Serial.write('\n');
    Serial.print(filesystem_member.name());

    if (!filesystem_member.isDirectory())
    {
      Serial.write('\t');
      Serial.print(filesystem_member.size());
      Serial.print(F(" byte"));
      Serial.write('\n');
    }

    filesystem_member.close();
  }

  filesystem_member.close();

  directory.rewindDirectory();
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  SD.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
directory = SD.open("/");
list_files();
directory.close();
Serial.println(freeMemory());
delay(2000);
}

I forgot directory.close(); line.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ercanersoy wrote:
I forgot directory.close(); line.

As clawson noted in post #9.

 

Please mark the solution - see Tip #5.

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It was #5 where I mentioned the .close() thing.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

so it was - I think I just scrolled backwards til the first mention I saw.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...