Ошибка [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;

Это не выглядит так хорошо для меня, но, по крайней мере, это работает

Другие вопросы по тегам