简体   繁体   中英

Can memory fragmentation cause an Arduino to run out of RAM even if the program uses less than half of the RAM?

I am using the Arduino Nano every which has 6kB RAM and am confident that I can write my program to use less than half of the RAM. My program has some variables in the void loop, one of which is a 10 character string, which are overwritten 10 times a second. There are additional variables including <10 character strings in functions that are also over written 10 times a second).

Surely, if I am using less than half of the RAM, then no matter how fragmented the RAM becomes, the memory allocator will always find holes large enough to fit the new data when some operation is performed on a variable?

I have already heard that strings are frowned upon on Arduinos. It does surprise me since char arrays are perfectly capable of causing memory fragmentation. I don't want to swap my strings for char arrays because I am using serial.readstring() to read the entire string from the serial port. To work with char, I would need to use serial.read() which only receives 1 character, making the process far more cumbersome.

If you aren't using dynamic memory you won't get memory fragmentation. Dynamic memory is allocated when you use malloc() and friends , or the new keyword, not typical in Arduino programs. Everything you mentioned is either on the stack which is a fixed size or allocated once for the life of the program.

I don't want to swap my strings for char arrays because I am using serial.readstring()

Serial.readString() returns a String object, the internal buffer for which (from the source , because it is not documented) is dynamically allocated (and reallocated if the size increases). Each allocation will be 8 byte aligned and include a block header which might be 8 bytes also, so the "overhead" space (that is space used but not available to the user of the allocated memory) for small allocations may be considerable in proportion to the user memory allocated.

Now you have to realise that dynamic memory allocations are from the heap and not all of your 6Kb will be allocated to the heap. First the linker will allocate all static data objects, then the heap, and what is left will be the available stack. On a 6Kb part there will hardly be any space for a usefully sized heap.

More generally using the system heap in embedded systems is a generally a bad idea - in this case through lack of memory is an issue, but in all cases lack of real-time deterministic behaviour and error handling in the event of exhaustion at run-time are issues.

See https://docs.arduino.cc/learn/programming/memory-guide for information on code that can be used to determine the available heap space on your board and other information about memory usage on Arduino.

Fragmentation may not be the issue rather then simple memory exhaustion. Fragmentation only occurs if you are repeatedly allocating and releasing blocks - if you allocate and never release, fragmentation will not occur. In the case of a String object, it's memory is released when it is destroyed - deleted for a dynamically created object or goes out of scope for a local object. String objects that are statically allocated will not be destroyed. Because String internally uses realloc() it can release memory if the string length increases - that can cause fragmentation perhaps, but that can be avoided by pre-allocationg sufficient capacity with String.reserve() .

The problem however is an easy one to solve and not at all "cumbersome" - at least not after you have written a suitable function (or copy and pasted it from here even). eg:

char* SerialReadString( Serial& port, char* buffer, size_t length, int timeout )
{
    int start = millis() ;
    size_t ci = 0u ;
    while( ci < length - 1 && 
           (port.available() != 0 || millis() - start <= timeout) )
    {
        int ch = port.read() ;
        if( ch > 0 )
        {
            buffer[ci] = ch ;
            buffer[ci+1] = 0 ;
        }
    }

    return buffer ;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM