簡體   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