Serious fopen() memory problem

05 Aug 2014

Hey guys, I seem to be experiencing serious memory problems with fopen() while trying to use SDFileSystem with mbed-rtos. Now, I realize this has come up several times before, and the usual solution is to increase the SD card thread's stack size to 2.25x the default stack size, but my problem is much more severe than that. In my case, I couldn't get fopen() to work until I increased the stack size to at least 1600B on an LPC11U24, 3.125x the default stack size! Furthermore, repeated calls to fopen() eventually causes a hang, presumably due to a memory leak. Using this modified version of the official test program, fopen() will hang the system after just 10 seconds, or about 100 calls:

main.cpp

#include "mbed.h"
#include "rtos.h"
#include "SDFileSystem.h"

DigitalOut myled(LED1);
DigitalOut sdled(LED2);
SDFileSystem sd(p5, p6, p7, p20, "sd");

void sd_thread(void const *argument)
{
    while (true) {
        sdled = !sdled;
        FILE* fp = fopen("/sd/test.txt", "w");
        if (fp != NULL) {
            fclose(fp);
        } else {
            error("Failed to open file!\n");
        }
        Thread::wait(100);
    }
}

int main()
{
    Thread sdTask(sd_thread, NULL, osPriorityNormal, 1600);
    while (true) {
        myled = !myled;
        Thread::wait(100);
    }
}


Occasionally I'll get an error pattern instead of a hang, but no text will print telling me what it is. I've also tried this with my new and improved SDFileSystem library with similar results.

UPDATE: Apparently the number of calls to fopen() before a hang is dependent on the program. I just tried a more comprehensive version that tests fread() in another thread, and it hung on the 3rd call to fopen().

06 Aug 2014

Hi,

This is probably same issue here: http://mbed.org/forum/bugs-suggestions/topic/3447/

The microlib version of fclose() doesn't call free() which is a bug. I have already reported this problem to ARM Compiler team and will let you know if we have proper fix.

Cheers, Toyo

06 Aug 2014

Thanks for the quick reply! If that's the case, then manually calling free() should solve the hang problem at least. However, is it normal for fopen() to require more than 1.5KB of stack space? What is it doing with all that RAM? I should point out that this was on an LPC11U24, I was unable to get another project of mine to work on an LPC1549 even at 4KB of stack. fopen() would just return NULL every time.

06 Aug 2014

Printing which sectors it reads from the SD card might give some insight already. But one sector is already 512 bytes. So if it currently keeps one file sector in its memory, thats 512 bytes. Next is that the file system isn't using the tiny config (which tbh might be an idea to set as standard imo):

Quote:

  1. define _FS_TINY 0 /* 0:Normal or 1:Tiny */

/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system / object instead of the sector buffer in the individual file object for file / data transfer. This reduces memory consumption 512 bytes each file object. */

So then we are already at 1kB. If it uses one more sector for something, or another temporary buffer or so, you are at 1.5kB.

06 Aug 2014

(wrong account)

06 Aug 2014

Except that according to the ARM library documentation, the memory for FILE objects is implicitly allocated on the heap, not the stack. Furthermore, both the LPC11U24 and LPC1549 are using microlib, which doesn't use FILE buffers, and only requires 20B per FILE object. By my count, that should bring us to less than 600B including FatFs's per-file buffer.

UPDATE: I just did a couple of tests with _FS_TINY set to 1, and I was able to run the test program with just 625B of stack. That's 975B less than the vanilla tests, and 463B less than expected! Clearly something strange is going on here...

18 Mar 2015

Hi Neil,

Did you ever get to the bottom of this?

18 Mar 2015

No, I gave up on the stdio layer. I've been using the ChaN FatFs API directly. It's much faster, and the memory consumption makes sense.

23 Mar 2015

Hi Neil, By using ChaN FatFs API directly, did you avoid all possible problems under RTOS ? I'm currently chasing a problem calling f_stat() under RTOS ... I used stat() before, but it was hanging the whole CPU very often. Now I got the problem again with f_stat(), but only in the main thread, and still working fine under the usb_thread(). The strange thing is that if FILINFO is on stack, I got the issue, but not if it is a global variable. I will probably submit question/issue soon...

27 Mar 2015

Hi again Neil, Facing others RTOS hangs problems accessing SDCard within threads, I decide to use ChaN FatFs API lower layer, avoiding stdio layer, which also give me pain with SerialDriver (I switched back some ports to older RawSerial to get rid of the issues). My problems with fopen() desappeared using f_open() from ChaN FatFs API, but it comes with a new problem : f_open() fails if called before SDCard properly mounted. I've added an called to sd.mount() in main thread, but it doesn't seems to work. I still need to call upper API calls before to make it works. Any ideas ?