Утечка памяти, вызванная конкатенацией строк

В этой ссылке, раздел «Память, память, память» было сказано, что последовательное выполнение множества конкатенаций строк, например: многократное использование оператора+(), приведет к фрагментации памяти, что может привести к тому, что общая куча не будет использована полностью.

Альтернатива, которую я предлагаю, — использовать strcat() с буферами символов и вообще не использовать строки, а затем преобразовать результирующий буфер символов в строку, если в конце требуется строка? Будет ли это спасением от фрагментации кучи?

Пояснение: я заранее укажу верхнюю границу буфера символов, как если бы я знал максимальный необходимый/который будет использоваться размер.

, 👍0


1 ответ


1

Ваш метод уменьшит фрагментацию. Но понадобится ли вашему приложению сделать это один раз? Несколько раз? Должно ли оно работать вечно? Если ваше приложение часто использует пары malloc()/free() или new/delete, оно будет фрагментировать кучу, вызывая ее рост и в конечном итоге вызывая коллизию стека. Дело не столько в том, что Arduino является устройством с ограниченными ресурсами; в конечном итоге это произойдет на любом постоянно работающем устройстве с фиксированным объемом памяти.

Если вы можете установить верхнюю границу требований к буферу, то предварительно распределите пул буферов глобально, локально как статический уровень файла или локально или в куче (с помощью malloc() [1]) — массив «достаточно больших» буферов, достаточного для вашего приложения. Затем всегда выделяйте/отменяйте выделение одного из них, и вы избежите фрагментации. Ваше приложение (или библиотека обработчиков буферов) должно будет отслеживать, какие буферы свободны, а какие используются, так же, как это делают системные распределители. Но в обмен на запись таким образом вы получаете возможность выделять и освобождать память навсегда, без фрагментации. Каждый запрос и каждый возврат имеют одинаковый размер, поэтому любой бесплатный фрагмент может заполнить запрос без необходимости увеличения пула.

Мое личное предпочтение — статическое распределение (на уровне файла или глобально видимое), потому что 1) оно поступает из нижней части памяти, что имеет тот же эффект, что и выделение в куче, и 2) оно объявлено как массив массивов, поэтому Синтаксис индексации массива работает без необходимости писать его вручную, как если бы вы использовали malloc() для большого фрагмента.

Примечание[1]: Хотя я предостерег от использования вызовов malloc() и free(), здесь и в других местах сайта, причиной фрагментации является повторное выделение и освобождение из кучи или из нее. Однако в этом случае я предлагаю использовать malloc() для выделения памяти, которая будет сохраняться до конца выполнения программы.

,