繁体   English   中英

即使程序使用不到一半的 RAM,memory 碎片是否会导致 Arduino 耗尽 RAM?

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

我正在使用 Arduino Nano,每个都有 6kB RAM,并且我相信我可以编写我的程序来使用不到一半的 RAM。 我的程序在 void 循环中有一些变量,其中一个是 10 个字符的字符串,每秒被覆盖 10 次。 还有其他变量,包括函数中的 <10 个字符串,每秒也被覆盖 10 次)。

当然,如果我使用的 RAM 不到一半,那么无论 RAM 变得多么碎片化,当对变量执行某些操作时,memory 分配器总是会找到足够大的孔来容纳新数据?

我已经听说 Arduinos 不赞成使用字符串。 这确实让我感到惊讶,因为 char arrays 完全能够导致 memory 碎片。 我不想将字符串换成 char arrays,因为我正在使用 serial.readstring() 从串口读取整个字符串。 要使用 char,我需要使用仅接收 1 个字符的 serial.read(),这使得该过程更加繁琐。

如果您不使用动态 memory,您将不会得到 memory 碎片。 动态 memory 是在您使用malloc()和朋友new关键字时分配的,这在 Arduino 程序中并不常见。 您提到的所有内容要么在固定大小的堆栈上,要么在程序的生命周期内分配一次。

我不想用我的字符串交换 char arrays 因为我正在使用 serial.readstring()

Serial.readString Serial.readString()返回一个String object,其内部缓冲区(来自,因为没有记录)是动态分配的(如果大小增加则重新分配)。 每个分配将是 8 字节对齐的,并包括一个块 header 也可能是 8 个字节,因此小分配的“开销”空间(即已使用但对已分配内存的用户不可用的空间)可能与用户 memory 已分配。

现在您必须意识到动态 memory 分配来自,并非所有 6Kb 都将分配给堆。 首先 linker 将分配所有 static 数据对象,然后是堆,剩下的将是可用堆栈。 在 6Kb 的部分上,几乎没有任何空间可容纳有用大小的堆。

更普遍地说,在嵌入式系统中使用系统堆通常是一个坏主意 - 在这种情况下,由于缺少 memory 是一个问题,但在所有情况下,在运行时耗尽的情况下都缺乏实时确定性行为和错误处理是问题。

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.

碎片可能不是问题,而是简单的 memory 耗尽。 仅当您重复分配和释放块时才会发生碎片 - 如果您分配并且从不释放,则不会发生碎片。 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对象不会被销毁。 因为String在内部使用realloc()它可以在字符串长度增加时释放 memory - 这可能会导致碎片,但是可以通过使用String.reserve()预先分配足够的容量来避免这种情况。

然而,这个问题很容易解决,而且一点也不“麻烦”——至少在你写了一个合适的 function 之后(或者甚至从这里复制并粘贴它)。 例如:

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 ;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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