Ошибка [Lp001] не хватает памяти, когда я не должен
В настоящее время я работаю над проектом, который использует различные языковые настройки. Для решения этой проблемы используется таблица для хранения всех текстов на разных языках, которые используются в программе. Поэтому, когда на экране будет написан текст, вызывается эта таблица, и в зависимости от того, какой текущий языковой параметр является текстовой строкой, возвращается. Недавно я присоединился к этому проекту и заметил, что способ его хранения не очень оптимизирован, и для каждого добавленного нового языка время, необходимое для поиска правильной строки, будет увеличиваться. Поэтому я придумал (на мой взгляд) лучшее решение. Однако, когда я попытался реализовать это, я столкнулся с проблемой получения ошибки, что слишком много памяти используется, и я не понимаю, почему. Я использую IAR Enbedded Workbench.
Исходное решение в псевдо / C++ коде:
typedef struct
{
enum textId;
enum language;
string textString;
} Text;
static const Text s_TextMap[] =
{
{ TextId::RESTORE_DATA_Q ,Language::ENGLISH ,"Restore Data?" },
{ TextId::RESTORE_DATA_Q ,Language::SWEDISH ,"Återställa data?" },
{ TextId::RESTORE_DATA_Q ,Language::GERMAN ,"Wiederherstellen von Daten?" },
{ TextId::CHANGE_LANGUAGE ,Language::ENGLISH ,"Change Language" },
{ TextId::CHANGE_LANGUAGE ,Language::SWEDISH ,"Välj språk" },
{ TextId::CHANGE_LANGUAGE ,Language::GERMAN ,"Sprache wählen" },
};
Мое решение в псевдо / C++ коде:
typedef struct
{
const char* pEngText;
const char* pSweText;
const char* pGerText;
} Texts;
static Texts addTexts(const char* pEngText, const char* pSweText, const char* pGerText)
{
Texts t;
t.pEngText = pEngText;
t.pSweText = pSweText;
t.pGerText = pGerText;
return t;
}
typedef struct
{
enum textId;
Texts texts;
} Text;
static const TextTest s_TextMapTest[] =
{
{TextId::RESTORE_DATA_Q, addTexts("Restore Data?","Återställa data?","Wiederherstellen von Daten?")},
{TextId::CHANGE_LANGUAGE, addTexts("Change Language","Välj språk","Sprache wählen")},
};
Мое решение очевидно быстрее для поиска в среднем случае, и, исходя из моих расчетов, оно также должно использовать меньше памяти. Когда используются полные таблицы, я подсчитал, что исходное решение требует 7668 байт, а мое решение - 4248 байт. Для этого я реализовал полные таблицы в небольшой тестовой программе и использовал sizeof(s_TextMap). Тем не менее, когда я пытаюсь скомпилировать код, я получаю сообщение об ошибке:
Ошибка [Lp011]: при размещении раздела не удалось выделить место для разделов / блоков с общим предполагаемым минимальным размером 0x130301 байтов (макс. Выравнивание 0x1000) в <[0x0000a000-0x0007ffff]> (общее количество незафиксированных пространств 0x757eb).
Ошибка [Lp011]: при размещении раздела не удалось выделить место для разделов / блоков с общим предполагаемым минимальным размером 0x47de4 байта (макс. Выравнивание 0x20) в <[0x1fff0000-0x2000fff0]> (всего незафиксированного пространства 0x1fff1).
Ошибка [Lp021]: место назначения для сжатого пакета инициализатора "USER_DEFAULT_MEMORY-1" размещается по адресу, который зависит от размера пакета, что недопустимо при использовании сжатия lz77. Попробуйте вместо этого использовать "инициализировать путем копирования с упаковкой = нули" (или ни одного).
Ошибка [Lp021]: место назначения для сжатого пакета инициализатора "USER_DEFAULT_MEMORY-1" размещается по адресу, который зависит от размера пакета, что недопустимо при использовании сжатия lz77. Попробуйте вместо этого использовать "инициализировать путем копирования с упаковкой = нули" (или ни одного).
Ошибка, которая меня больше всего смущает, это первая ошибка, в которой говорится, что мой код занимает 0x130301 байт памяти, и я не вижу, как это возможно. Может ли это быть какая-то ошибка в IAR или я что-то упустил?
2 ответа
В вашем решении s_TextMapTest[]
будет обязательно находиться в ОЗУ, а не в ПЗУ, поскольку указатели устанавливаются во время выполнения - хотя неясно, как вам удалось использовать вызов функции в качестве инициализатора элемента массива. На большинстве микроконтроллеров ОЗУ является гораздо более ограниченным ресурсом. Вы не предоставили никакой информации о цели или ее карте памяти.
В любом случае вы должны проверить выходные данные карты памяти вашего компоновщика, чтобы убедиться, что данные расположены надлежащим образом и там, где вы ожидаете.
Исходный код и решение, которое вы предлагаете в своем собственном ответе, доступно для чтения.
Решение, которое сохраняет форму вашего исходного предложения, оставаясь при этом доступным для чтения, - это написать addTexts()
как макрос, а не функция:
#define addTexts( eng, swe, ger, fin ) {eng, swe, ger, fin}
хотя я не вижу, в чем преимущество, а вы на самом деле не "добавляете" текст - текст всегда был там при инициализации.
Итак, мне удалось заставить его работать. Я перекомпоновал дополнительную структуру и функции и просто упростил ее до:
typedef struct
{
TextId::e textId;
const char* pEngText;
const char* pSweText;
const char* pGerText;
const char* pFinText;
} Text;
Это не выглядит так хорошо для меня, но, по крайней мере, это работает